tag:blogger.com,1999:blog-57462515711023586242024-03-14T02:03:30.452-07:00SteamCodeA blog about code, music, books, etc.slabountyhttp://www.blogger.com/profile/06122119234374455724noreply@blogger.comBlogger88125tag:blogger.com,1999:blog-5746251571102358624.post-82820520039726051232013-10-20T19:04:00.000-07:002013-10-20T19:04:14.794-07:00Letter Frequency in Text and RailsThe other day a coworker and I were discussing keyboard layouts and this led into whether or not the character frequency (how often various letters are used) in a Rails application would be the same as it would be in normal text (though obviously, the code will have many more and more varied special characters). I thought that it would be but, he didn't think that would be the case. Since I had a bit of free time this weekend, I thought I'd write a bit of code to figure it out. For the text, I used Project Gutenberg's copy of <a href="http://www.gutenberg.org/ebooks/2701">Moby Dick</a> and for the code, I used a smallish Rails project of mine.<br />
<br />
Here's the code and results ...<br />
<br />
<script src="https://gist.github.com/slabounty/7071036.js"></script><br />
<br />
As you can see, the histograms are pretty similar. For this particular Rails project, I was using HAML, so I'm not sure if there'd be any differences if you used erb or not. Also, as I noted, this was a fairly small project.<br />
<br />
The code runs against a single file that's passed in on the command line. So run it like this ...<br />
<br />
<code>ruby letter_freqency.rb moby10b.txt > moby_results.txt</code><br />
<br />
for example. For a rails project, I cat'd all the files together and then ran the code like this ...<br />
<br />
<code>
cat `find . -iname \*.rb -or -iname \*.haml` > rails_files.txt<br />
ruby letter_freqency.rb rails_files.txt > rails_results.txt<br />
</code>
<br/>
Let me know if you try this on one of your projects and post the results in the comments.slabountyhttp://www.blogger.com/profile/06122119234374455724noreply@blogger.com0tag:blogger.com,1999:blog-5746251571102358624.post-85279245040573599752013-09-29T18:58:00.000-07:002013-09-29T18:58:19.724-07:00Rails and WindowsIn a word ... "Don't".<br />
<br />
I often see posts, especially on <a href="http://www.linkedin.com/">LinkedIn</a>, with titles like "How do I learn Rails" etc. My advice is always to start with Michael Hartl's <a href="http://ruby.railstutorial.org/">Rails Tutorial</a>. A related question that often comes up though is about using Windows to do this. There are often comments that you can use Windows for this, cross-platform is good, etc. The truth though is that you're not going to have a lot of success developing Rails on Windows and if you're looking to move into Rails development as a profession, it will not probably help. There are a few different reasons for this, but first let's take a look a why you <b>should </b>develop for Windows.<br />
<br />
If you've decided that Windows is a great platform and that you're ready to do your part to bring it to the Rails community, then by all means, go for it. Very few in the Rails community do use Windows, but if someone was willing to do the work to make everything that's commonly used work together under Windows, then I think it would be welcomed with open arms.<br />
<br />
If you're just trying to learn some Rails though, this is probably not a good approach. While you're developing, you're going to have issues come up and those that can help you are going to be few and far between. In fact, even if it's not a problem with Windows per se, the fact that it works on Mac/Linux (or even appears to work there), is going to make it hard to get others interested in the problem. You're almost certainly going to have to come up with a failing test case (you should anyway) and show that this is the case. The problems you are, in general, going to be different than you'd see on a either a Mac or Linux and so most Rails developers won't have seen them and won't be able to help you solve them. Also, a big part of Rails development is done with the command line and while you can get bash or some other Unixy shell running, it's going to be sub-optimal.<br />
<br />
For someone who is looking to move into Rails development, this is probably even more true. You're going to have all the issues listed above and those problems and their solutions won't be relevant to the issues your co-workers are going to be having. Additionally, whatever tools (here I'm thinking of editors and editor plugins especially) get adopted internally are unlikely to work well or even at all on Windows. A big part of the Rails development experience is collaboration and you won't really be able to benefit from or contribute to this collaborative process.<br />
<br />
So, I recommend either breaking down and buying a Mac (a pretty expensive idea if you're just looking to experiment) or dual booting using Ubuntu (a pretty common platform where you'll be able to get some help easily if you run into issues).<br />
<br />
Good luck and I'd be glad to hear your thoughts in the comments and in this case I wouldn't mind all that much being proven wrong.slabountyhttp://www.blogger.com/profile/06122119234374455724noreply@blogger.com6tag:blogger.com,1999:blog-5746251571102358624.post-6417214368208553322013-07-28T16:48:00.000-07:002013-07-28T16:48:02.365-07:00Interviewing ReduxIn my<a href="http://steamcode.blogspot.com/2013/07/interviewing-classic-mistake.html"> last post</a> I talked about interviewing and overrepresenting your knowledge. We had a similar situation with a different candidate and I'd like to talk about that a bit.<br />
<br />
A typical interview question that I've used and had used on me goes something like "What blogs do you read regularly?". It's generally used as a conversation starter to see what you're interested in and how much you stay up on things. The candidate in question told us that he read "lots of blogs" but when pressed couldn't name a single one or even talk about a post he'd read recently. As with our other candidate, he could have probably redeemed himself but didn't.<br />
<br />
You should be reading blogs. I'd suggest at least three or four with a mix of ruby/rails and general technology. <a href="http://robots.thoughtbot.com/">thoughtbot</a> is good along with <a href="http://www.ruby-lang.org/en/news/">Ruby News</a>. and <a href="http://rubysource.com/">ruby source</a>. Before any interview make sure that you've read one or two posts pretty in depth and be prepared to talk about it a bit.<br />
<br />
If you have other suggestions for blogs to read or thoughts on interviewing (either side of the table), be sure to leave them in the comments.slabountyhttp://www.blogger.com/profile/06122119234374455724noreply@blogger.com2tag:blogger.com,1999:blog-5746251571102358624.post-47889739187962354402013-07-20T15:51:00.000-07:002013-07-20T15:51:14.813-07:00Interviewing Classic MistakeWe were interviewing a for a position the other day, when the interviewee made the pretty classic mistake of overrepresenting his knowledge on a particular subject. In this particular case it was puppet/chef, although I've seen it happen a number of times over the years. His resume should have been a warning, he listed a large number of technologies that he knew ... actually far more than he could have known. You should keep your list down to a handful of things that you know really well. Anyway, we've been looking at puppet recently for building our machines and using them for development also and since this was on his resume, one of my coworkers asked him about it. "Oh yeah, I love puppet and chef." was the reply. "Great, where have you used them and what did you like about them? Also, where do you think each is strongest?". "Well ... I haven't really used them in production, more just played with them." Hmmmm... at this point he's not making a very good showing. If you come out that you "love" a technology, then you probably should have done more than "play" with it. "OK, then exactly how did you play with them? Did you run the tutorial?". "Yes, I ran the tutorial". By this time, we weren't even sure that he'd run the tutorial or just read a blog post or something. He probably could have redeemed himself after this (he didn't), but it would have been difficult.<br />
<br />
In general in interviews, you don't want to be talking about things you don't know about. You really want to be talking about things that you do know about. If you don't know something, don't put it on your resume and certainly don't say much more than you've "read about it, it seems really interesting, and you'd just love to learn more about it here at XYZ Corp when you start."
slabountyhttp://www.blogger.com/profile/06122119234374455724noreply@blogger.com0tag:blogger.com,1999:blog-5746251571102358624.post-49305873321134885662012-01-29T16:34:00.000-08:002012-01-29T17:45:34.147-08:00Rails / Ajax / AutocompleteAs you all know if you're regular readers here, I started out in the Ruby web framework world with Ramaze and I'm definitely glad that I did. However, it doesn't seem like there's much of a job market for Ramaze programmers, so I've taken up using Rails, specifically Rails 3.1. There's a number of great books for Rails and the one I'd recommend is Ruby on Rails 3 Tutorial by Michael Hartl. In this book, he develops a Twitter like application in Rails starting with basic pages and moving on to more complex topics. <br /><br />I've been working on a simple project for a greeting card application and I came up with a little something that might be interesting. The cards have a recipient and can have multiple signers. I added autocomplete for the recipient, but it was a bit harder for the comma separated list of signers. What I ended up doing was was simply grabbing the last piece of the list in the controller and passing that back to the view. <br /><br />Here's the view code ...<br /><br /><pre class="sh_ruby"><br /><h1> Create a Card </h1><br /><%= image_tag "card_images/#{@template.image_name}", :size => "200x200" %><br /><%= form_tag ("create_from_image") do %><br /><br /> <%= label_tag("Add the recipient's email: ") %><p/><br /> <%= text_field_tag(:recipient_email, "#{@recipient_email}")%><p/><br /><br /> <%= label_tag("Add A Greeting: ") %><p/><br /> <%= text_field_tag(:greeting, "#{@greeting}")%><p/><br /><br /> <%= label_tag("Add the signers' emails (comma separated): ") %><p/><br /> <%= text_field_tag(:signers_email, "#{@signers}")%><p/><br /><br /> <%= hidden_field_tag :template_id, @template.id %><br /><br /> <%= submit_tag("Preview the card!") %><br /> <%= submit_tag("Send the card!") %><br /><% end %><br /></pre><br /><br />There's nothing very interesting in here, but the main field we're interested in is the :signers_email text field.<br /><br />Here's the javascript code for it ...<br /><br /><pre class="sh_javascript"><br />$(document).ready(function(){<br /> // Below is the name of the textfield that will be autocomplete<br /> $('#recipient_email, #signers_email').autocomplete({<br /> // This shows the min length of charcters that must be <br /> // typed before the autocomplete looks for a match.<br /> minLength: 2,<br /> // This is the source of the auocomplete suggestions. In this case a <br /> // list of emails from the users controller, in JSON format.<br /> source: '/users/index.json'<br /> })<br /><br />});<br /></pre><br /><br />What this says is that for both the recipient_email and signers_email fields, use autocomplete, send when we have two characters, and use the /users/index.json function to get the data we need.<br /><br />Finally, we have the controller code ...<br /><br /><pre class="sh_ruby"><br /> def index<br /> @title = "All users"<br /> @suggestion = "Pick someone and send them a card!"<br /> if params[:term]<br /> search_term = params[:term].split(",").last.strip<br /> @users = User.find(:all, :conditions => ['email LIKE ?', "#{search_term}%"])<br /> @users_hash = []<br /> @users.each do |user|<br /> @users_hash << { "label" => user.email }<br /> end<br /><br /> else<br /> @users = User.where(:active => true).paginate(:page => params[:page])<br /> end<br /><br /> respond_to do |format|<br /> format.html<br /><br /> # Here is where you can specify how to handle the request for "/people.json"<br /> format.json { render :json => @users_hash }<br /> end<br /> end<br /></pre><br /><br />Here, we have a couple of things going on ... for the Ajax side, we'll get the params[:term] field so we know that we need to get the constrained list. First, we're going to grab the params[:term] value, which should look something like "abc@test.com, def". Here we'd like to look for emails that start with the "def" and ignore the "abc@test.com" piece. So ... we split on the comma, grab the final element in the array, and then remove any leftover spaces at the end or beginning of the string. Next, we'll create an array where each element is a hash of the form { "label" => "defghi@test.com" }. This is the form that the jquery autocomplete needs. Finally, we use the respond_to section to send this back as json.<br /><br />As always, let me know if you have questions.slabountyhttp://www.blogger.com/profile/06122119234374455724noreply@blogger.com0tag:blogger.com,1999:blog-5746251571102358624.post-35393289281642661882011-12-18T18:22:00.000-08:002011-12-18T18:30:46.580-08:00Majority VotingI saw this one over at <a href="http://programmingpraxis.com/2011/12/16/majority-voting/">Programming Praxis</a>. It's pretty simple with ruby, but there's one slightly interesting piece in there that might come in handy sometime. Here's the code ...<br /><br /><pre class="sh_ruby"><br />def majority(l)<br /> h = Hash.new(0)<br /> l.each { |v| h[v] += 1 }<br /> max = h.max {|a,b| a[1] <=> b[1]}<br /> max[1] >= l.length / 2.0 ? "#{max[0]} won with #{max[1]} out of #{l.length} total votes" : "No winner"<br />end<br /><br />v1 = %w[A A A C C B B C C C B C C]<br />v2 = %w[A B C A B C A]<br /><br />puts "v1 = #{majority(v1)}"<br />puts "v2 = #{majority(v2)}"<br /></pre><br /><br />OK, so we create a Hash where the value in the key/value pair is initialized to 0 and we add one each time time we see a vote. Here's the cool part, we use the max function from Enumerable knowing that max itself uses <code>each</code> which will give us the key/value pair as a two element array. So, we set the function to compare the second element, the value, of the pair. The max that gets returned will also be a two element array and we use that to calculate whether there's a winner or not.<br /><br />These types of problems are great for sharpening your programming skills in general and your ruby skills in particular. They're exactly the types of questions that end up on programming interview tests.<br /><br />Let me know if you have questions or comments.slabountyhttp://www.blogger.com/profile/06122119234374455724noreply@blogger.com0tag:blogger.com,1999:blog-5746251571102358624.post-2888279755524738112011-11-14T19:52:00.000-08:002011-11-14T20:19:54.327-08:00CentroidsHere's another one from my clustering code, slightly modified for explanatory purposes. This post was spurred by a conversation with a couple of friends when we were talking about programming, who said that programming languages mostly had the same things (i.e. everything old is new again). While I'm not completely in opposition to that, I think that some of the newer languages (read Ruby) do have a lot to offer when it comes to compactness. <br /><br />Here the problem is to find the centroid of a number of points. Basically, we want the averages of all the first values of the points, the second values of the points, etc. Let's show an example ... <br /><br />If we have [[x0, y0, z0], [x1, y1, z1], ... [xn, yn, zn]] as our points then the centroid would be the point given by [sum(x's) / n, sum(y's)/n, sum(z's) / n] (and here I'm too lazy to figure out how to create the capital Sigma for sum). Think about how you might solve this in your favorite programming language. In C/C++ anyway, you'd need to know in advance how many points and how many dimensions (the example above uses three, but it could be more or less). In Java, you don't need that, but I don't think you could do something like this ...<br /><br /><br /><pre class="sh_ruby"><br /> def centroid(x)<br /> x[0].zip(*x[1..x.length-1]).map { |v| v.inject(:+) / v.length.to_f }<br /> end<br /></pre><br /><br />OK, so what's going on here? First up we're going to take the first element of the array (above the [x0, y0, z0]) and <code>zip</code> it with the rest of the array with <code>*x[1..x.length-1]</code>. This should give us, once again from the example above [[x0, x1, ...xn], [y0, y1, ... yn], [z0, z1 ... zn]]. So basically, a new array with all the x's gathered together, the y's, etc. Now comes <code>map</code>. Here, we'll take each element, which is itself an array and then use <code>inject</code> to run through each of the items, say [x0, x1, ... xn] and sum them together. Finally, we'll divide by the length of the element to get an average. If it's hard to see this, break it into pieces and then run it through using irb. It should be a bit easier to see there.<br /><br />So, what's the point here. Well, essentially you could this in any programming language or in fact any Turing machine, but the language itself can make it easier freeing you to do other things or harder.<br /><br />Let me know if you have any questions or comments.slabountyhttp://www.blogger.com/profile/06122119234374455724noreply@blogger.com0tag:blogger.com,1999:blog-5746251571102358624.post-4387118938604078822011-11-11T13:45:00.000-08:002011-11-11T13:57:01.543-08:00Monty Hall ProblemA friend of mine got asked this question in an interview yesterday and I thought it'd make an interesting programming problem. It goes something like this ... Suppose you're on a game show and are offered the choice of one of three doors. Behind one of the doors is a car and behind the other two are goats. Let's say you choose door number three (see Jimmy Buffet song). At this point Monty Hall shows you that behind door number one is a goat and offers to let you switch to door number two. The question is, should you do it? The easy (and incorrect answer) is that it doesn't matter. The correct answer is that, yes you should. Why? I'll let you look it up or you can just run the following program ...<br /><br /><pre class="sh_ruby"><br />possible_doors = [:goat, :goat, :car].permutation.to_a<br />bad_choice = 0<br />tries = 100000<br />1.upto tries do |mc|<br /> test_doors = possible_doors[Random.rand(possible_doors.length)]<br /> bad_choice += 1 if test_doors[Random.rand(test_doors.length)] == :car<br />end<br />puts "bad_choice percent = #{bad_choice.to_f / tries.to_f * 100} good_choice percent = #{100.0 - (bad_choice.to_f / tries.to_f * 100)}"<br /></pre><br /><br />First up, we get a list of all the possible ways the doors could be arranged and set the number of times that switching would be a bad choice to 0. We'll run this 100000 times in a Monte (not Monty) Carlo loop. In the loop we get one of the possible arrangements of test doors randomly selected and then increment the bad_choice variable if the door we pick contains the car (in other words switching from where we are would be a "bad choice"). When we run this program we see that switching is a bad choice only about 33% of the time and a good choice about 66% of the time (one might guess that these are really 33.333333...% and 66.6666666%). So, then answer in this case is that yes you should switch.<br /><br />Let me know if you have questions or comments.slabountyhttp://www.blogger.com/profile/06122119234374455724noreply@blogger.com0tag:blogger.com,1999:blog-5746251571102358624.post-59850955861447964162011-11-01T18:30:00.000-07:002011-11-01T18:47:02.341-07:00Ruby Distance CalculationI was just looking at a clustering algorithm and needed a distance calculation between two points in n-dimensional space. If you remember your high school geometry (or even earlier) the distance between two points in the xy plane is the sqrt((x1 - x2)**2 + (y1-y2)**2). Where the two points are represented by (x1, y1) and (x2, y2). For more dimensions, just add values inside the sqrt as in (z1-z2)**2 for a third dimension. Given that here's a one line function that I came up with <br /><br /><pre class="sh_ruby"><br />def distance(a, b)<br /> Math.sqrt(a.zip(b).inject(0) { |d, c| d + (c[0] - c[1]) ** 2 })<br />end<br /></pre><br /><br />It's a bit tricky, so let's go through it. First we have the <code>Math.sqrt</code> which will just take the square root of whatever is inside it. Next the <code>a.zip(b)</code> will take two arrays (here the input parameters) and take the first values of each of the arrays, create a new array from them and then add that to the output array (see also this <a href="http://steamcode.blogspot.com/2011/05/arrayzip-and-upside-up-numbers.html">post</a> for more information on zip). Same with the second values of the arrays and so on. For example if we have <code>[x1, y1, z1].zip([x2, y2, z2])</code> this will return <code>[[x1, x2], [y1, y2], [z1, z2]]</code> (hopefully, this looks like something we can use to you). Next we're going to use <code>inject</code> to run through this array with a starting value of 0 (d) and add to it the square of the difference of the two values in the array. Finally as noted before, take the square root and return. <br /><br />If you have any problems with this, break it up into multiple lines and check the intermediate values. As always, let me know if you have any questions.slabountyhttp://www.blogger.com/profile/06122119234374455724noreply@blogger.com1tag:blogger.com,1999:blog-5746251571102358624.post-45697461975326697162011-10-05T18:35:00.000-07:002011-10-05T18:51:21.205-07:00HeapsI noted in my <a href="http://steamcode.blogspot.com/2011/10/phone-interview-1.html">last post</a> that I had a technical phone interview. When it was scheduled, the HR person told me that it would include "data structures, algorithms, and architecture". I decided that it wouldn't be a bad idea to review a bit and so I got a copy of Steven Skiena's "<a href="http://www.amazon.com/Algorithm-Design-Manual-Steven-Skiena/dp/1849967202/ref=sr_1_1?ie=UTF8&qid=1317865138&sr=8-1">The Algorithm Design Manual</a>" and started rummaging through it. <br /><br />One of the data structures that I came across was a heap (as in heapsort if you've forgotten). A heap is a binary tree data structure that has the property that the parent is smaller for a min-heap or larger for a max-heap than its children. They can be used for priority queues as the minimum or maximum is always at the top of the heap or for sorting assuming that you a) take the top element and then b) recalculate the tree. <br /><br />The code here follows Skiena's pretty closely excepting he starts his array at 1 and I use the more natural (for me anyway) 0 start. This code also implements only a min-heap, but you should take a bit of time to see if you can figure out how to make it either a min-heap or a max-heap as an initialization parameter. A couple of other things aren't that pretty (<code>extract_min!</code> in particular bugs me), but mostly it's not bad and is straight forward. <br /><br />So ... here's the code <br /><br /><pre class="sh_ruby"><br />class Heap<br /> def initialize(a)<br /> @q = []<br /> a.each { |v| insert(v) } if a<br /> end<br /><br /> def parent(n)<br /> n == 0 ? -1 : (n-1) / 2<br /> end<br /><br /> def young_child(n)<br /> (2 * n) + 1<br /> end<br /><br /> def insert(v)<br /> @q << v<br /> bubble_up(@q.size-1)<br /> end<br /><br /> def bubble_up(n)<br /> return if parent(n) == -1 # Root of heap, no parent <br /> if @q[parent(n)] > @q[n]<br /> swap(n, parent(n))<br /> bubble_up(parent(n))<br /> end<br /> end<br /><br /> def swap(n, pn)<br /> @q[n], @q[pn] = @q[pn], @q[n]<br /> end<br /><br /> def min<br /> @q.first<br /> end<br /><br /> def extract_min!<br /> m, @q[0] = @q.first, @q.last<br /> @q.pop<br /> bubble_down(0)<br /> m<br /> end<br /> <br /> def bubble_down(n)<br /> c = young_child(n)<br /> min_index = n<br /><br /> 0.upto(1) { |i| min_index = c+i if ((c+i) <= @q.size-1) &&(@q[min_index] > @q[c+i]) }<br /><br /> if (min_index != n)<br /> swap(n, min_index)<br /> bubble_down(min_index)<br /> end<br /> end<br /><br /> def sort!<br /> a = []<br /> while v = extract_min! do a << v end<br /> a<br /> end<br />end<br /><br />h = Heap.new([12, 14, 6, 10, 8, 27, 1, 4, 9])<br />puts "extract_min! = #{h.extract_min!}"<br />puts "extract_min! = #{h.extract_min!}"<br />puts "extract_min! = #{h.extract_min!}"<br />puts "extract_min! = #{h.extract_min!}"<br />puts "min = #{h.min}"<br />puts "min = #{h.min}"<br />puts "sort! = #{h.sort!}"<br /></pre><br /><br />Let me know if you have any questions or comments and if you make improvements, post those too.slabountyhttp://www.blogger.com/profile/06122119234374455724noreply@blogger.com0tag:blogger.com,1999:blog-5746251571102358624.post-24875595310526710742011-10-04T10:10:00.000-07:002011-10-04T10:50:47.473-07:00Phone Interview - 1I had a phone interview with a great company yesterday and thought I'd share some of the questions, my answers, what I think might have been better answers, and some additional potential questions that might have been asked. First, this was for a manager position and the fact that they're asking technical questions as part of the interview process and as the first interview really impressed me. It shows that they value technical abilities and respect their engineers and developers enough to hire managers that are technically capable as a top priority. We started out, as is usually the case with a bit of small talk about myself, the interviewer, and the company. Nothing too interesting there. I don't recall the actual order of the questions, but I think I got them all.<br /><br />1. What are horizontal and vertical scaling? Here I knew what horizontal scaling was, but I don't believe I've heard the term vertical scaling. Horizontal scaling means adding more servers to give more processing power while vertical scaling (as I learned when I looked it up) is beefing up the capabilities of an existing server by adding say memory, CPUs, or CPU power. A reasonable follow up to this would have been to discuss the advantages and disadvantages to each.<br /><br />2. What is object oriented programming? Here I discussed encapsulation and inheritance. I probably should have mentioned polymorphism and message passing. The <a href="http://en.wikipedia.org/wiki/Object_oriented_programming">Wikipedia article</a> is pretty decent and wouldn't be a bad place to do a high level review for this sort of question. I was a little surprised that I didn't get a question on a specific problem. I always would as someone to list out objects and methods for a card game or for a file system (stolen I believe from Steve Yegge if I remember correctly). <br /><br />3. Given an unsorted list, how would you find a duplicate element. This one was interesting because it had recently appeared on <a href="http://programmingpraxis.com/2011/09/23/array-duplicates/">Programming Praxis</a>. I solved it there and used a hash table. The idea is to run through each element of the list and put it on the hash table. If when you go to put it on the hash table, there's something already there, then you've found the duplicate and should return it.<br /><br />4. In the above question, what's the complexity using Big O notation. Here, since we're running through the list just once, it should be O(n) where n is the size of the list.<br /><br />5. How does a hash table work or how is it implemented "under the hood"? There are actually a couple of ways of implementing hash tables. I gave the answer of an array of linked lists. You have an array of size n and then use the element that you're going to put on the table to generate a hash value using a hash function. Then use this mod n and add it to the linked list that's at that element. <br /><br />6. How would you count the number of 1's in an integer? This is pretty classic. Probably the easiest is to use a shift/and technique. You would "and" the value with "1" and if it's non-zero (actually it'll be 1) then add one to the bit count. Shift right and repeat until the value is 0.<br /><br />7. The final question was about Design Patterns and whether I knew about them and why they're useful. My response was that they're useful in that they give us a way to discuss our designs with a common language. People were using design patterns before the GoF book, but they codified the patterns and gave them names. This makes it much easier to talk about these things.<br /><br />I think that was all of the questions. We then talked a bit about the position and the company in general. As I said, I was very impressed with them and their "corporate culture". <br /><br />So ... what sorts of things do you ask or have you been asked in technical phone interviews? Anything interesting or unique? Let us know in the comments.slabountyhttp://www.blogger.com/profile/06122119234374455724noreply@blogger.com0tag:blogger.com,1999:blog-5746251571102358624.post-10303349872107601842011-09-13T20:03:00.000-07:002011-09-13T20:16:02.312-07:00Tetrahedral NumbersHere's another one from <a href="http://programmingpraxis.com/2011/09/13/tetrahedral-numbers/">Programming Praxis</a> this one on tetrahedral numbers. I'll leave you to read the description and just jump straight into the ruby solution. The interesting thing here is to use a <code>lambda</code> to create a method that we can pass around. Here's the entire program ...<br /><br /><pre class="sh_ruby"><br /><br />def linear(target, f)<br /> n = 1<br /> while ( f.call(n) != target)<br /> n = n + 1<br /> end<br /> n<br />end<br /><br />def binary(target, f)<br /> low, high = 1, 2<br /> while (f.call(high) < target) do high = high*2 end<br /> mid = (high + low) / 2<br /> while (fmid = f.call(mid)) != target do<br /> fmid < target ? (low, mid = mid, (mid + high) / 2) : (high, mid = mid, (low + mid) / 2)<br /> end<br /> mid<br />end<br /><br /><br />tetrahedral = lambda { |n| n * (n + 1) * (n + 2) / 6 }<br /><br />1.upto(10) { |i| puts tetrahedral.call(i) }<br /><br />puts linear(169179692512835000, tetrahedral)<br />puts binary(169179692512835000, tetrahedral)<br /></pre><br /><br />We start out with two methods <code>linear</code> and <code>binary</code> which are pretty straightforward with the exception that both take a function (in this case <code>f</code>) as a parameter. For linear, we start at 1 and continue calling <code>f</code> until the value of <code>f(n)</code> is the same as <code>target</code>. <code>binary</code> is similar, but here we keep doubling the <code>high</code> value until we're above the <code>target</code> and then we calculate the <code>fmid</code> and use it as a high or low value until we converge. <br /><br />The <code>tetrahedral</code> function itself is created with a lambda so that we can pass it to the other two methods. The next lines are simply tests. Note how much longer the <code>linear</code> method takes than the <code>binary</code>. <br /><br />As always, let me know if you have questions or comments.slabountyhttp://www.blogger.com/profile/06122119234374455724noreply@blogger.com0tag:blogger.com,1999:blog-5746251571102358624.post-61532485330456550762011-09-03T17:10:00.001-07:002011-09-03T17:25:32.718-07:00Two String Exercise via Programming PraxisHere's another one (or two rather) from <a href="http://programmingpraxis.com/2011/09/02/two-string-exercises/">Programming Praxis</a>. Let's take a look at the second one first as it's trivial in ruby. If we're given a string, how do we replace multiple spaces with single spaces. F/or example the string <code>"a b c"<code> would become <code>"a b c"</code>. For both of these, we're going to monkey patch the string class. Here's the code ...
<br />
<br /><pre class="sh_ruby">
<br />class String
<br /> def remove_consecutive_spaces
<br /> self.gsub(/ +/, " ")
<br /> end
<br />end
<br /></pre>
<br />
<br />All we do is do a global substitution of one or more spaces with a single space. This would be quite a bit trickier in C say which is why it ends up in interview questions.
<br />
<br />The second (or first) problem is to remove duplicate characters from a string. For example, <code>"aaaabbbb"</code> becomes <code>"ab"</code> and <code>"abcbd"</code> becomes <code>"abcd"</code>. This one is a bit trickier but shows another good example of how useful <code>inject()</code> can be. Here's the code ...
<br />
<br /><pre class="sh_ruby">
<br />class String
<br /> def remove_duplicate_characters
<br /> self.split(//).inject([]) { |a, c| a << c if !a.include?(c); a }.join
<br /> end
<br />end
<br /></pre>
<br />
<br />Going through it from left to right, we have first the <code>split(//)</code> which will turn the array into a string of characters. With that string of characters we do an <code>inject([])</code> which a) initializes a new empty array (sometimes called the "memo") and then runs through the character array adding a character "c" to the array "a" if it's not already there <code>include?</code>. The <code>; a</code> returns the current array back to the <code>inject</code>. Finally, we recreate the string by doing a <code>join</code> on the character string array.
<br />
<br />Let me know if you have questions or comments.slabountyhttp://www.blogger.com/profile/06122119234374455724noreply@blogger.com0tag:blogger.com,1999:blog-5746251571102358624.post-34610066537921002392011-08-11T17:04:00.000-07:002011-08-11T17:35:24.975-07:00Hett's ProblemSorry for not writing for a while, I've been busy looking for a new job. If you've got one, you can contact me here or at slabounty at large search company that starts with "g".
<br />
<br />Anyway ... over at <a href="http://programmingpraxis.com/2011/08/09/hetts-problem-128/">Programming Praxis</a> there's a problem via <a href="https://sites.google.com/site/prologsite/prolog-problems/1">PrologSite</a> concerning lists. Here's the problem statement ...
<br /><blockquote>1.28 (**) Sorting a list of lists according to length of sublists
<br />a) We suppose that a list (InList) contains elements that are lists themselves. The objective is to sort the elements of InList according to their length. E.g. short lists first, longer lists later, or vice versa.
<br />
<br />Example:
<br />?- lsort([[a,b,c],[d,e],[f,g,h],[d,e],[i,j,k,l],[m,n],[o]],L).
<br />L = [[o], [d, e], [d, e], [m, n], [a, b, c], [f, g, h], [i, j, k, l]]
<br />
<br />b) Again, we suppose that a list (InList) contains elements that are lists themselves. But this time the objective is to sort the elements of InList according to their length frequency; i.e. in the default, where sorting is done ascendingly, lists with rare lengths are placed first, others with a more frequent length come later.
<br />
<br />Example:
<br />?- lfsort([[a,b,c],[d,e],[f,g,h],[d,e],[i,j,k,l],[m,n],[o]],L).
<br />L = [[i, j, k, l], [o], [a, b, c], [f, g, h], [d, e], [d, e], [m, n]]
<br />
<br />Note that in the above example, the first two lists in the result L have length 4 and 1, both lengths appear just once. The third and forth list have length 3; there are two list of this length. And finally, the last three lists have length 2. This is the most frequent length.</blockquote>
<br />
<br />So how can we solve these two problems in Ruby? The first one is pretty much trivial. Here's the code ...
<br />
<br /><pre class="sh_ruby">
<br />list = [%w[a, b, c], %w[d], %w[e, f], %w[g, h, i, j, k], %w[l], %w[m, n, o]]
<br />list_sort_length = list.sort {|a, b| a.length <=> b.length}
<br />p list_sort_length
<br /></pre>
<br />
<br />All we're going to do is use the option to <code>sort</code> that takes a block. The block will get two values and instead of the default, we're going to use the values <code>length</code>. Run this and you should see ...
<br /><output>[["l"], ["d"], ["e,", "f"], ["a,", "b,", "c"], ["m,", "n,", "o"], ["g,", "h,", "i,", "j,", "k"]]</output>.
<br />
<br />The next piece is a bit trickier. Here, we can't do just a one-liner (that I could see anyway). Here's the code ...
<br />
<br /><pre class="sh_ruby">
<br />hist = Hash.new{|h, k| h[k] = []}
<br />list.each { |l| hist[l.length] << l }
<br />list_sort_hist = []
<br />hist.sort {|a,b| a.length <=> b.length}.each { |key, value| value.each {|e| list_sort_hist << e } }
<br />p list_sort_hist
<br /></pre>
<br />
<br />We start out creating the histogram hash and passing a block so that each element is initialized with an empty array. Then, we work through the list and add each element to an array at the appropriate histogram hash location. Next, create the empty sorted histogram array. Finally, we're going to sort the histogram the same way that we did in the earlier problem (we can do this because they both are Enumerable. We take the result of that and do and <code>each</code> for every item in the histogram. For each of the <code>value</code>s (which remember are arrays), we add them to the <code>list_sort_hist</code> array. Finally, we print that out. If it makes it easier to see, split that long line in two. First create a sorted histogram array and then for each value loop through the value and add it to the list_sort_hist array.
<br />
<br />Let me know if you have any comments, questions, or jobs.slabountyhttp://www.blogger.com/profile/06122119234374455724noreply@blogger.com3tag:blogger.com,1999:blog-5746251571102358624.post-24607069847040196202011-05-28T15:08:00.000-07:002011-05-28T15:25:55.209-07:00Array.zip() and Upside Up NumbersI've known about the zip method for arrays but have never really found much of a use for it. I was working a problem on <a href="http://programmingpraxis.com/2011/05/27/upside-up/">Programming Praxis</a> the other day and saw some Python solutions that used it, so I decided to give it a try in my solution. Let's start out with how it works.<br /><br />In the simplest case, we have an array and we zip it with an array of the same size. Here's what it looks like ...<br /><br /><pre class="sh_ruby"><br />a = [1, 2, 3]<br />b = [4, 5, 6]<br />a.zip(b) => [[1,4], [2,5], [3,6]]<br /></pre><br /><br />We can see that we end up with an array that's the same size as the original arrays made up of elements of each of the arrays. We can also zip multiple arrays ...<br /><br /><pre class="sh_ruby"><br />a = [1, 2, 3]<br />b = [4, 5, 6]<br />c = [7, 8, 9]<br />d = %w[a, b, c]<br />a.zip(b, c, d) => [[1, 4, 7, "a,"], [2, 5, 8, "b,"], [3, 6, 9, "c"]] <br /></pre><br /><br />With that here's the documented code for the upside_up program including, at the beginning, the original requirements from Programming Praxis ...<br /><br /><pre class="sh_ruby"><br /># An “upside up” number is a number that reads the same when it is rotated<br /># 180°. For instance, 689 and 1961 are upside up numbers.<br /><br /># Your task is to find the next upside up number greater than 1961, and to<br /># count the number of upside up numbers less than ten thousand. When you are<br /># finished, you are welcome to read or run a suggested solution, or to post<br /># your own solution or discuss the exercise in the comments below.<br />#<br /># Create an array of pairs that can match. We should end up with<br /># UPSIDE_DICT = [[0, 0], [1, 1], [6, 9], [8, 8], [9, 6]] <br />UPSIDE_DICT = %w[0 1 6 8 9].zip(%w[0 1 9 8 6])<br /><br /># Open the Integer class and add the upside_up? method that returns true/false<br /># based on whether the integer is an upside number or not.<br /># Let's take this a piece at a time:<br /># 1) self.to_s.split(//) will give us an array of characters for the given number<br /># such as [1, 9, 6, 1]<br /># 2) zip this array with<br /># 3) self.to_s.split(//).reverse will give us the array above reversed ...<br /># [1, 6, 9, 1]<br /># 4) and zipping the two together should give us something like ...<br /># [[1, 1], [9, 6], [6, 9], [1, 1]]<br /># 5) Now, we'll loop through the above zipped array using inject and make sure that every pair<br /># in it is also in the UPSIDE_DICT array. If all of them are, then we'll return<br /># true otherwise the inject() will return false.<br />class Integer<br /> def upside_up?<br /> self.to_s.split(//).zip(self.to_s.split(//).reverse).inject(true) { |r,v| r && UPSIDE_DICT.include?(v) }<br /> end<br />end<br /><br /># Find all the upside values up to 10000 and print them.<br />(1..10000).each do |v|<br /> puts "#{v} is an upside number" if v.upside_up?<br />end<br /></pre><br /><br />Be sure to let me know if you have questions or comments.slabountyhttp://www.blogger.com/profile/06122119234374455724noreply@blogger.com1tag:blogger.com,1999:blog-5746251571102358624.post-27433147800737968392011-05-18T05:57:00.000-07:002011-05-18T07:44:02.830-07:00InterviewingI had a young person come in for an internship interview a couple of days ago and it made me realize that I've never posted anything outside the programming world. I'm going to try to do a few different posts on the subject of interviews and resumes to hopefully help give some perspective to the hiring process from someone who actually hires rather than someone who tries to get you hired (head hunter). Is my perspective better than theirs? No probably not, but it may be a bit different.<br /><br />With any interview there are going to be both soft questions and hard questions. By this I don't mean easy and hard but personality questions and technical questions. Let's start by looking at some of the soft questions you might get and why they're asked in the first place. The first thing to remember here is that you're going to be part of a group (as an aside, I hate the term "team" unless you're all dressed the same). Because of this, the hiring manager is going to want to know how you're going to fit in with the rest of the group and the soft questions will be used to try to ascertain that.<br /><br />One question that seems to get asked is "Tell me about yourself". This is where you should discuss your interests related to the job. Since the interviewer is most likely going to ask about job related items later, now is a good time to bring up any outside projects that might relate. Open source projects that you've done or contributed to or a blog that you write (programming/technical related) are things that will get the interviewer's attention. Just about anything technically related is a good thing to bring up.<br /><br />You're also almost certain to get a question on a group project that you worked on. Here, it won't matter if you're a developer with 20 years experience or a new grad, you'll probably have to talk about working with other people. The question may be as straight forward as "Tell me about a project that you worked on with other people." or it may be more subtle "Tell me about your last project" with the expectation that this involved other people. As you talk about this project, you may get follow on questions such as "Were there any personal issues between people in the group?" or "Was there anyone in the group who didn't pull their weight?". Then these will be followed up with "How did these issues get resolved?". All of these questions are geared towards finding out how well you will fit in in a group situation. And, as a subtext, the interviewer will be looking for your "leadership" capabilities. All of these questions are a chance for you to show that you will work well in a group and not just work well but make the whole group work better. In the example of someone not pulling their weight, stating that you noticed that Fred wasn't doing what was expected, you could tell how you talked with Fred and let him know that you'd noticed his work wasn't as good as it had been and then worked with him to get him back up to speed. In the case of personality issues, discuss how in a meeting where things were getting tense, you played the peacemaker by making sure that both sides got heard and then working through the issues.<br /><br />There's probably more, but these are the types of questions that I'll usually pursue, these (or similar ones) and then follow ons based on the responses I receive. The thing to remember though is that all of these soft questions are designed for better or worse to figure out if you will fit in the group structure. Try to approach them in this way and you should do fine.<br /><br />As always, let me know if you have questions or comments.slabountyhttp://www.blogger.com/profile/06122119234374455724noreply@blogger.com0tag:blogger.com,1999:blog-5746251571102358624.post-84726728026381376442011-04-20T06:28:00.000-07:002011-04-20T06:47:49.290-07:00All TrueI was working a problem on <a href="http://programmingpraxis.com/2011/04/19/same-five-digits/">Programming Praxis</a> yesterday and ended up writing a little piece of code that returned true if every element in a hash was true. It used inject and I thought it would be worth posting a generalized version here.<br /><br /><pre class="sh_ruby"><br />module Enumerable<br /> def all_true<br /> self.inject(true) { |r, v| r && (yield v) }<br /> end<br />end<br /></pre><br /><br />We start by <a href="http://en.wikipedia.org/wiki/Monkey_patch">monkey patching</a> the <code>Enumerable</code> module which will make it available for <code>Array</code>s, <code>Hash</code>es, etc., basically anything that includes <code>Enumerable</code>. Next, we define the method <code>all_true</code>. The only line in the method is an <code>inject</code> which we initialize with <code>true</code> and then give it a block with two parameters, the r(esult) and the v(alue). We then <code>and/&&</code> the r(esult) with whatever the yield of the v(alue) returns.<br /><br />You can test it with the following code ...<br /><br /><pre class="sh_ruby"><br />puts "#{[2, 4, 6, 8].all_true { |n| n%2 == 0 }}"<br />puts "#{[2, 4, 7, 8].all_true { |n| n%2 == 0 }}"<br /><br />puts "#{{ 2=>2, 4=>4, 6=>6, 8=>8}.all_true { |n| n[0]%2 == 0 && n[1]%2 == 0 }}"<br />puts "#{{ 2=>2, 4=>4, 7=>7, 8=>8}.all_true { |n| n[0]%2 == 0 && n[1]%2 == 0 }}"<br /></pre><br /><br />The first two of each set will return true, the second false.<br /><br />As I've been doing the <a href="http://programmingpraxis.com/">Programming Praxis</a> problems, I've found myself using <code>inject</code> and its close relative <code>map/collect</code> more and more. I think this is partly because of the types of problems posted there and the influence of the solutions that are generated which tend to be <a href="http://en.wikipedia.org/wiki/Functional_programming">functional programming</a> based. At any rate, having a good understanding of both <code>inject</code> and <code>map/collect</code> will serve you well and simplify many of your day to day programming tasks.<br /><br />Let me know if you have questions or comments.slabountyhttp://www.blogger.com/profile/06122119234374455724noreply@blogger.com0tag:blogger.com,1999:blog-5746251571102358624.post-53541082239456343982011-03-29T14:02:00.001-07:002011-03-29T14:09:20.213-07:00Nanoc and No Compiling or RoutingHere's a short post on using nanoc with files that you just want copied from the content directory to the output directory unchanged. For these types of files, it's best if you have them in their own subdirectory (say images or css). Let's say we have some images (.jpg, .png, etc.). First just put them in an images directory under content. Then we need to add a couple of rules to our Rules files ...<br /><br /><pre class="sh_ruby"><br />compile '/images/*/' do <br /> # Leave everything in the images directory as is.<br />end <br /></pre><br /><br />and then a bit later on in the routing section ...<br /><br /><pre class="sh_ruby"><br />route '/images/*/' do <br /> # Make sure that /images/some_image/ is routed to <br /> # /images/some_image.jpg or /images/some_image.png or so <br /> item.identifier.chop + '.' + item[:extension] <br />end <br /></pre><br /><br />I didn't do an actual project and put it up on GitHub for this one, but if this isn't clear, then let me know and I can do that too.slabountyhttp://www.blogger.com/profile/06122119234374455724noreply@blogger.com0tag:blogger.com,1999:blog-5746251571102358624.post-45467518121440466192011-03-25T09:21:00.000-07:002011-03-25T09:46:27.887-07:00Nanoc and Multiple Layout TemplatesA while back we took a <a href="http://steamcode.blogspot.com/2011/01/nanoc-and-static-web-sites.html">quick look</a> at <a href="http://nanoc.stoneship.org/">nanoc</a> for generating static web sites. I've been using it a bit both experimenting and for a simple web site for an author friend of mine. I'm going to do a few short articles on using it, documenting what I've learned in much the same way I've tried to do with Ramaze. <br /><br />Let's start with some simple code that uses multiple layout templates. You have this often with web sites where there's a home page that uses a different layout than the rest of the pages of the site. Let's start with creating a new site. We do that the same way we did last time with ...<br /><br /><code>nanoc create_site multiple_templates</code><br /><br />and let's add a couple of pages to go along with them ...<br /><br /><code>nanoc create_item page1</code><br /><code>nanoc create_item page2</code><br /><br />We didn't really talk about the Rules in the last post and I'm only going to touch on them now. You should take a few minutes and read a bit about them <a href="http://nanoc.stoneship.org/docs/4-basic-concepts/#rules">here</a>. We'll discuss them a bit more as we go through future posts.<br /><br />Now, we need to modify the Rules file to tell it to use an alternate layout for the content/page[12].html files. I'm not going to show the entire file, just the compile rule for these ...<br /><br /><pre class="sh_ruby"><br />compile '/page*/' do<br /> filter :erb<br /> layout 'page'<br />end<br /></pre><br /><br />What this rule says is that when we "compile" files in our content/ directory, we should first run them through the <a href="http://www.ruby-doc.org/stdlib/libdoc/erb/rdoc/">erb</a> (embedded ruby) and then use the page template in the layouts directory.<br /><br />Here's the default which will get use by everything else (essentially our main page at content/index.html).<br /><br /><pre class="sh_ruby"><br />compile '*' do<br /> filter :erb<br /> layout 'default'<br />end<br /></pre><br /><br />This along with the code for all of this up on <a href="https://github.com/slabounty/multiple_templates">github</a> should be enough to get you started. As always though, let me know if you have questions or comments.slabountyhttp://www.blogger.com/profile/06122119234374455724noreply@blogger.com0tag:blogger.com,1999:blog-5746251571102358624.post-58759627327795583042011-03-01T14:05:00.000-08:002011-03-01T14:22:26.136-08:00InkscapeThis one is going to be short since I'm not a designer. I've been reading <a href="http://www.amazon.com/Web-Design-Developers-Programmers-Techniques/dp/1934356131/ref=sr_1_1?s=books&ie=UTF8&qid=1299017288&sr=1-1">"Web Design for Developers"</a> by Brian P. Hogan and he recommends using <a href="http://www.adobe.com/products/illustrator/">Illustrator</a> for parts of his book. Since the cost was a bit umm... prohibitive for learning purposes, I started looking around for a suitable alternative. What I found was <a href="http://inkscape.org/">Inkscape</a>. This is a nice little program for generating SVG (Scalable Vector Graphics) files. You can use it for generating files for say logos or banners on websites. While I won't say it's simple to use (and this probably says more about me than the program), with the tutorials available, you shouldn't have too much problem getting it to work. Additionally, there's a book on it that's reviewed on <a href="http://books.slashdot.org/story/11/02/28/1430231/Book-Review-Inkscape-048-Essentials-for-Web-Designers">Slashdot</a>. I haven't read the book yet but do have it on order and if it seems worthwhile, I'll post here about it.<br /><br />To install ...<br /><br /><kbd>sudo apt-get install inkscape</kbd> <br /><br />and you should have an inkscape selection Applications/Graphics or at least on Ubuntu.<br /><br />Once again, I'm not sure how much I'll be able to help, but if you have questions, be sure and let me know.slabountyhttp://www.blogger.com/profile/06122119234374455724noreply@blogger.com0tag:blogger.com,1999:blog-5746251571102358624.post-15492769323968372192011-01-28T05:43:00.000-08:002011-01-28T06:37:04.195-08:00Nanoc and Static Web SitesA few days ago we <a href="http://steamcode.blogspot.com/2011/01/webby-and-static-web-sites.html">looked at</a> <a href="http://webby.rubyforge.org/">Webby</a> for generating static web sites. I had a couple of issues with it, including the fact that it didn't work with ruby 1.9.2 and it hasn't been updated for a couple of years now. Someone on the Ramaze email list suggested that I should take a look at <a href="http://nanoc.stoneship.org/">nanoc</a> too. It seems to have many of the same features as webby, but is actively maintained and runs on ruby 1.9.2. So let's take a look at getting it up, running, and generating a site. First, we'll need to add a few gems ...<br /><br /><code><br />gem install nanoc<br />gem install kramdown<br />gem install adsf<br /></code><br /><br />Here we're installing nanoc itself, <a href="http://kramdown.rubyforge.org/">kramdown</a>, which is a Markdown converter, and <a href="http://stoneship.org/software/adsf/">adsf</a>, which is used as a web server for showing the site.<br /><br />With that out of the way, let's go ahead and create a new site ...<br /><br /><code>nanoc create_site my_site</code><br /><br />This should create a new site in the directory my_site that has a few different files and directories. Go ahead and cd into the directory and then<br /><br /><code>nanoc compile</code><br /><br />which should "compile" the site. In this case, compile will create an output directory where the resulting HTML files will reside. OK, now we can start a web server with <br /><br /><code>nanoc view</code> <br /><br />and then point our browser at http://localhost:3000. At this point you should see the default site for nanoc. For viewing, you could also use<br /><br /><code>nanoc autocompile</code><br /><br />which will also compile a file when changes are made to the site automatically. For "real" work, this is probably the option to use. <br /><br />OK, let's take a look at the content directory. This is where nanoc will keep the files that will get compiled and moved to the output directory. Go ahead and open up content/index.html in your <a href="http://www.vim.org/">favorite text editor</a> and make a few changes. Go back to the browser, reload, and you should see your changes there. Now, take a look at layout/default.html. If you make a change in there, say adding an h1 tag before the h2 Documentation tag, it will appear in all the pages that are generated. <br /><br />Finally, we're going to need to add new pages if this is going to be useful. Try this ...<br /><br /><code>nanoc create_item test</code><br /><br />This will create a test.htnml in the content directory and when it gets compiled, you should be able to go to http://localhost:3000/test/ (don't forget the final "/") and see the page. A couple of things to note here. In the output directory, this will be output/test/index.html. <br /><br />This should be enough to get you started. Definitely check out the <a href="http://nanoc.stoneship.org/">nanoc site</a> for more information. I'm going to use this to generate a personal site, so I'll let you know how it goes and what good/bad things I see.<br /><br />Let me know if you have questions or comments.slabountyhttp://www.blogger.com/profile/06122119234374455724noreply@blogger.com2tag:blogger.com,1999:blog-5746251571102358624.post-56769819301426605802011-01-25T18:07:00.000-08:002011-01-25T18:13:48.470-08:00Ruby and Rational NumbersHere's a problem over on <a href="http://programmingpraxis.com/2011/01/25/rational-numbers/">Programming Praxis</a> that for whatever reason I wasn't having much luck posting there. Their loss, your gain ;-). Here's the code ...<br /><br /><pre class="sh_ruby"><br />class Fraction<br /><br /> attr_reader :n, :d<br /><br /> def initialize(n, d)<br /> raise "Can't have zero denominator." if d == 0 <br /><br /> n, d = -n, -d if d < 0<br /><br /> g = n.gcd(d)<br /> if g == 1<br /> @n = n<br /> @d = d<br /> else<br /> @n = n / g<br /> @d = n / g<br /> end<br /> end<br /><br /> def plus(f)<br /> Fraction.new((@n*f.d)+(@d*f.n), @d*f.d)<br /> end<br /><br /> def minus(f)<br /> Fraction.new((@n*f.d)-(@d*f.n), @d*f.d)<br /> end<br /><br /> def times(f)<br /> Fraction.new(@n*f.n, @d*f.d)<br /> end<br /><br /> def divide(f)<br /> Fraction.new(@n*f.d, @d*f.n)<br /> end<br /><br /> def to_s<br /> "#{@n}/#{@d}"<br /> end<br />end<br /><br />f1 = Fraction.new(1, 3)<br />f2 = Fraction.new(-1, 7)<br />puts "#{f1} + #{f2} = #{f1.plus(f2)}"<br />puts "#{f1} + #{f2} = #{f1.minus(f2)}"<br />puts "#{f1} + #{f2} = #{f1.times(f2)}"<br />puts "#{f1} + #{f2} = #{f1.divide(f2)}"<br /></pre><br /><br />Nothing too awfully complex here, but if you have questions, let me know.slabountyhttp://www.blogger.com/profile/06122119234374455724noreply@blogger.com0tag:blogger.com,1999:blog-5746251571102358624.post-29440618826783167142011-01-24T19:13:00.001-08:002011-01-24T19:35:49.281-08:00Webby and Static Web SitesI was trying to figure out recently how to build a static site with Ramaze and didn't really come up with anything, but someone pointed me in the direction of <a href="http://webby.rubyforge.org/">Webby</a> that's designed with just this use case in mind. It seems pretty cool, so I thought I'd document how to get it up and running on Ubuntu. <br /><br />First I tried just doing a gem install, but that didn't work because I'm using ruby 1.9.2 so ...<br /><br /><code>rvm install 1.8.7</code><br /><br />to get the right ruby (assuming you're using rvm to manage this). Then, you'll need to set the correct ruby with <br /><br /><code>rvm 1.8.7</code><br /><br />to add the following gems for ruby 1.8.7<br /><br /><code><br />gem install webby<br />gem install RedCloth<br /></code><br /><br />The RedCloth gem is needed for the default, but if you decide to use a different templating system, you don't need to install it.<br /><br />OK, let's create a web site now.<br /><br /><code>webby-gen website my_site</code><br /><br />There should now be a directory called my_site with a few different directories. Now you can<br /><code><br />cd my_site<br />webby<br /></code><br /><br />and this should create a new directory called output with some HTML files and the css for the site. If you modify the file index.txt in the content directory, and then rerun the <code>webby</code> command, you should see the output/index.html change. <br /><br />Since you've been reading this blog, you probably have a pretty good idea of how templating works, so there really shouldn't be too much here that you haven't seen in general even if you haven't looked at the RedCloth templating. webby also supports a number of other templating systems that you can use by setting a filter in the content file. This is documented in the <a href="http://webby.rubyforge.org/">User Manual</a>.<br /><br />To be honest, I just started looking at this today, so I'm not sure how much help I'm going to be with questions, but let me know if you have any and I'll give them a shot.slabountyhttp://www.blogger.com/profile/06122119234374455724noreply@blogger.com0tag:blogger.com,1999:blog-5746251571102358624.post-14865430296144704642010-11-30T05:52:00.000-08:002010-11-30T06:11:09.650-08:00Ruby 1.9.2 and RamazeOK, I just found out something interesting about ruby 1.9.2. They've changed the default LOAD_PATH to not include "." (current directory). What's this actually mean? Well, for starters just about every example that I and most others have written will no longer work. Here's an example with something from the current Ramaze prototype (generated when you do a <code>ramaze create foo</code><br /><br /><code>require 'model/user'</code><br /><br />this will generate errors if you run it with ruby 1.9.2. What you'll need to do instead is either<br /><br /><code>__DIR__('user')</code><br /><br />or <br /><br /><code>require_relative 'user'</code><br /><br />The first version is compatible between 1.9 and 1.8 and the 2nd is 1.9 only. Both examples assume that the file this code is in is already in the model directory. <br /><br />I should also note that Lee Jarvis has fixed the problem with the prototype already and it should be in the next update of Ramaze.<br /><br />Like I said, most of my examples from previous posts are now wrong, but they should be pretty easy to fix once you know how. If you have any problems, be sure to let me know and I'll try to help get them worked out with you.slabountyhttp://www.blogger.com/profile/06122119234374455724noreply@blogger.com1tag:blogger.com,1999:blog-5746251571102358624.post-85258849891712389012010-11-24T08:52:00.000-08:002010-11-24T08:55:29.321-08:00Ruby Book - $10This is a pretty good deal for the latest Ruby pickaxe book from Dave Thomas and the Pragmatic Programmer group. It's $10 each for the paper or electronic version of the book. Head over <a href="http://www.pragprog.com/titles/ruby3/programming-ruby-1-9?utm_source=MadMimi&utm_medium=email&utm_content=[Bookshelf]+Updated+Programming+Ruby+now+in+epub%2C+mobi+and+on+sale&utm_campaign=[Bookshelf]+Updated+Programming+Ruby+now+in+epub%2C+mobi+and+on+sale&utm_term=pragprog_com_2Ftitles_2Fruby3">here</a> to grab it.slabountyhttp://www.blogger.com/profile/06122119234374455724noreply@blogger.com0