## Posts Tagged ‘ruby’

### Smoothly parameterized ease curve

Thursday, May 23rd, 2013

Using polynomial ease curves, it’s easy to create a function f(x) which obtains f(0) = 0 and f(1) = 1 as well as reaching 0 derivatives f’(0) = 0, f’(1) = 0, f”(0) = 0, f”(1) = 0, etc. One can start with a simple cubic polynomial:

f(x) = 3x²-2x³

which achieves first order smoothness (i.e. f’(0) = 0 and f’(1) = 0. Then we can compose this to have higher and higher continuity f(f(x)), f(f(f(x))). This creates a 9th and 27th order polynomials. Here’s a sequence of repeated composing this cubic function. The title shows the order:

We can also derive such a smooth, symmetric polynomial ease curve for any order 2*k+1, k in ℕ+ polynomial. Thus with k we can have finer, albeit incremental, control over the shape of the function. Here’s a ruby script to generate a maple script that will generate the necessary coefficients (there must be a pattern here, but I’m too lazy right now to find it):

``````
#!/opt/local/bin/ruby
# Script to generate Maple code for solving for 2*k+1 order polynomial f(x)
# with value f(0) = 0, f(1) = 2 and dkf/dxk|0 = 0 dcf/dxc|1 = 1, c=1,...,k
smoothness = 3
(1..smoothness).each do |k|
as = (k+1..2*k+1).map{|c| "a#{c}"}.join(",");
puts "f := (#{as},x) -> "
puts "  #{(k+1..2*k+1).map{|c| "a#{c}*x^#{c}"}.join("+")};"
puts "solve({"
puts "  f(#{as},0)=0,"
puts "  f(#{as},1)=1,"
diffs = (1..k).map do |c|
"  eval(diff(f(#{as},x),#{(1..c).map{|d| "x"}.join(",")}),x=0)=0,\n"+
"  eval(diff(f(#{as},x),#{(1..c).map{|d| "x"}.join(",")}),x=1)=0"
end
puts "#{diffs.join(",\n")}},"
puts "  {#{(k+1..2*k+1).map{|c| "a#{c}"}.join(",")}});"
end
``````

Using these coefficients we can plot the first few:

These sequences converge on a scaled and shifted Heaviside step function. But we only have an integer-valued parameter. It’d be nice to have a smooth parameter.

If we only cared about this property of the curve getting steeper in the middle as we increase or parameter (while maintaining interpolation and at least C1 continuity, then we could try to do this with a cubic spline. Now we can smoothly increase the steepness, but before reaching the step function the spline curves to far, losing injectivity when treated as a function of x.

The fact the we cannot reproduce the Heaviside function with
a cubic spline should have been obvious anyway. The Heaviside function is loosely a degree ∞ polynomial, with ∞ smoothness at 0 and 1.

We can achieve what we want by taking a function which indeed converges to the Heaviside step function:

f(x) = 1/(1+e-2tx).

We can adapt this to our unit square domain and enforce interpolation for any k:

g(x) = (f(2x-1)-1/2)/(f(1)-1/2)/2+1/2,

or in MATLAB:

``````
g = @(x,t) (1./(1+exp(-2*t*(2*x-1)))-1/2)/(1./(1+exp(-2*t*1))-1/2)/2+1/2);
``````

This function behaves pretty nicely for t in (0,∞), going from a linear function to the Heaviside step function:

To achieve kth order continuity at our endpoints we can just run this function through (i.e. compose with) one of the 2k+1 order polynomials above. That way, with t we smoothly span a whole space of kth order smooth ease curves. For example, if h(x) = 3x&sup2-2x³ then this is h(g(x)):

### Backup DVD of television show to .mkv files

Sunday, March 3rd, 2013

I bought some DVDs of a german tv show. With my fancy macbook air, I unfortunately have no way to play them: no DVD drive!

So I dusted off my old laptop and installed `vobcopy` then I copied each dvd first to the old laptop from the disks using:

``````
vobcopy -m
``````

Then I copied these over to my macbook air. But these are just the raw dvd files (VIDEO_TS/*.VOB), which are rather large and unwieldy. To convert these to .mkv files I know to use Handbrake, but since I want to extract each of the 3 or 4 episodes per DVD, setting up Handbrake for each episode turned out to be too tedious. The presets in Handbrake don’t include options to extract all audio channels and all subtitles by default. Instead I found a ruby script call hb.rb which can set up batch jobs.

So finally to extract my episodes with all subtitles and all audio channels in tact I used:

``./hb.rb --verbose --input ~/Downloads/IM_ANGESICHT_DES_VERBRECHENS_D2 --output "~/Downloads/#title#_#pos#.mkv" --min-length 00:10:00 --max-length 00:50:00 --skip-duplicates --audio-copy --skip-commentaries --only-first-track-per-language --autocrop``

### Homonym translator

Sunday, March 13th, 2011

I wrote a little ruby program that accepts a string and translates as many words as it can to homonyms.
Save this in a file called homotranslate.rb:

``````
#!/usr/local/bin/ruby -w

class Homo
def initialize(filename)
homonyms = lines.collect{|e| e.strip.split(' ')};
@homo_map = Hash.new;
homonyms.each{|h| h.each{|e| @homo_map[e] = h - [e]; }; };
end

def random_translate(str)
str.gsub(/\w+/) do |word|
lw = word.downcase;

if(@homo_map[lw].nil? || word.size == 0)
word;
else
homonym = @homo_map[lw][rand(@homo_map[lw].size)];
if(word[0] >= 'A'[0] and word[0] <= 'Z'[0])
homonym.capitalize!
end
homonym;
end
end
end
end

# Default main program
if \$0 == __FILE__
homo = Homo.new("homonyms.txt");
end
__END__
``````

Then run with:

``````
echo "I owe you." | ruby homotranslate.rb
``````

Or just try it online now:

Random homonym translator web app
Source
ASCII list of homonyms, one set per line, space separated

### Ruby plus equals (+=) versus append/concatenation shovel (<<)

Wednesday, September 8th, 2010

I was stunned to watch how slow a recent ruby program was. All it was doing was concatenating a bunch of string literals in a big loop. Originally I was using plus equals:

``````
str = ""
1000.times do |i|
str += "foo bar"
end
``````

On a whim I tried switching to using an array then joining:

``````
str = ""
str_array = []
1000.times do |i|
str_array << "foo bar"
end
str = str_array.join
``````

Already this was way faster. I wrote up a little benchmarking program to see just how badly "+=" performs compared to "<<". I compare string +=, to the array set up I have above, and just using "<<" on the string:

``````
str = ""
1000.times do |i|
str << "foo bar"
end
``````

Here's my little test program.

``````
#!/usr/bin/ruby

power = 20

power.times do |p|
n = 2**p
str = ""
start_time = Time.now
n.times do |i|
str += "x"
end
duration = Time.now - start_time
#puts "#{n} string appends took: #{duration}s"
puts "#{n} #{duration}"
end

power.times do |p|
n = 2**p
str3 = ""
start_time = Time.now
n.times do |i|
str3 << "x"
end
duration = Time.now - start_time
puts "#{n} #{duration}"
end

power.times do |p|
n = 2**p
str2 = ""
start_time = Time.now
str_array = []
n.times do |i|
str_array << "x"
end
str2 = str_array.join
duration = Time.now - start_time
puts "#{n} #{duration}"
end
``````

And here are the results:

String += is asymptotically worse than <<. Reading through the ruby doc on strings its clear this is because:

``````
str1 += str2
``````

is syntactic sugar for something like

``````
str1 = str1 + str2
``````

whose "=" creates a new string object, hence the big computational cost.

But why?! I can't think of any reason why "+=" shouldn't be syntactic sugar for "<<". Can you?

Update:
I get it!
Here's two short snippets that illustrate the difference:

``````
a = "x"
b = a
b += "y"
a
``````

Which results in "x"

``````
a = "x"
b = a
b << "y"
a
``````

Which results in "xy"

It's subjective whether x+=y should mean "append y to x" or always be syntactic sugar for "x = x + y". My vote is for the later, which means I must be content that in Ruby these operators do different things and thus have different speeds.

### Music clock

Monday, January 11th, 2010

The music clock is an invisible clock. It tells the time through musical
tones. For now, it reads the hour and the minutes mod 12. Hopefully I will be
able to explore this idea and come up with a universally understandable and
recognizable system.

I use ajax requests and ruby and sox on the backend to make this work.

### “Recipe organizer and sharing interface”

Monday, January 4th, 2010

“Recipe organizer and sharing interface” is a recipe organizer and sharing web interface. It’s the Ruby on Rails app I wrote for my final class project in my senior year of college.

### Escape source code for posting online

Tuesday, November 10th, 2009

I put up an in browser version of my ruby version of escape-copy. You can copy and paste in your code into the form and my program escapes it for you in two ways. In one of the results boxes I just escape the input for <pre> and <code> tags (escape all of the less than and greater than symbols). In the other I escape everything necessary to paste into a generic (unicode?) HTML tag.

Try it out:

### List audiobooks and/or music based on directories: Ruby Version

Thursday, November 5th, 2009

I previously posted a bash script to count and print plain text and html listings of a directory: intended for displaying audiobook and music libraries. I recently tried to use the bash script on a large directory and it stalled because `sed` can’t handle large input. Here’s a ruby version that does the same thing:

``````
#!/usr/bin/ruby -w
usage = "Usage: list [filename] [directory]
If filename ends with .html then output will be html,
else output will be plain text."
if not ARGV[0] or not ARGV[1]
puts usage
elsif not File.directory? ARGV[1]
puts "list: #{ARGV[1]} is not a directory"
puts usage
else
dir = ARGV[1]
# should be quoted?
plain = (`ls -1 "#{dir}"/*`+"\n")
if(ARGV[0] =~ /.html\$/i)
plain = plain.split("\n")
author_count = plain.find_all{|line| line=~/:\$/}.length
title_count = plain.find_all{|line| line=~/[^:]\$/}.length
body = plain.collect do |line|
line.gsub(
/(.*)([^:])\$/,'      \1\2</br>').gsub(
/^\s*\$/,'    </div>').gsub(
/.*\/(.*):\$/,'    <h3>\1</h3>'+"\n"+'    <div class="books">')
end
output = "<html>
<meta http-equiv='Content-Type' content='text/html; charset=UTF-8'/>
<style type='text/css'>
body {
font : 10pt verdana;
background: white;
width: 95%
}
h2 {
margin: 15px 0px 5px 0px;
}
h3 {
margin: 15px 0px 5px 0px;
}
.books {
border: 1px solid #dddddd;
background: #eeeeff;
}
</style>
<body>
<h2>#{title_count} titles and #{author_count} authors</h2>
#{body.join("\n")}</div>
</body>
</html>"
else
output = plain;
end
File.open(ARGV[0], 'w') {|f| f.write(output) }
end
``````

### Escape code for html <pre> or <code> tag into clipboard: Ruby Version

Thursday, November 5th, 2009

I previously posted a bash script to speed up posting code in a <pre> or <code> tag in an html page or blog. The script escapes all less than and greater than symbols (< with &lt; and > with &gt;) in a given file then puts the results in the clipboard to facilitate pasting into a text area or text editor. I have now rewritten this idea in ruby. Now you can either `cat` in a file to the ruby script using pipe, or enter (paste) the input text directly. Save the following the ruby source in a file called `escape-copy.rb`:

``````
#!/usr/bin/ruby -w
# Usage:
# cat input_file | ruby escape-copy.rb | pbcopy
# or
# ruby escape-copy.rb | pbcopy
# (enter or paste your text then CTRL-D on its own line as EOF)
``````

Note: I of course used `escape-copy.rb` to make posting the source above super easy!

Sunday, October 25th, 2009

I finished coding a rather simple but addictive and challenging puzzle game, I’m calling the Google images game. The player is presented with the image results of a Google images search for some search word or phrase. The playerâ€™s objective is to guess and figure out what that search phrase was. Play it now!

The game is an amalgamation of php, javascript and ruby. The ajax javascript for the game is rather complicated by now to handle all of the gaming options, but it’s all visible in the game’s page source. I use a little ruby program to grab the initial google images thumbnails:

``````
#!/usr/bin/ruby
require 'uri'
require 'net/http'
require 'cgi'

SAFE_VALUES = ["on","moderate","off"]
cgi = CGI.new("html3")
safe = "moderate"
safe = cgi["safe"] if(!cgi["safe"].empty? and SAFE_VALUES.include?(cgi["safe"]))
target = ""
target = cgi["target"] if(!cgi["target"].empty?)

if(!cgi["query"].empty?)
cgi["query"].gsub(/ /,"+")+"&safe="+safe
http = Net::HTTP.new(uri.host, uri.port)
"User-Agent" => "Mozilla/4.0 (compatible; MSIE 5.5; Windows NT 5.0)"
}

if (code >= 200 && code < 300) then

#the data is available...
response = ""
response = response + chunk
end
images = []
response.scan(
/imgurl=(.+?)&imgrefurl=(.+?)&[^<]+<img src=(.+?) /
) do |img, ref, thumb|
images<<[img,ref, thumb]
end
images.collect! do |e|
"<a title='"+e[1]+" 'href='"+
CGI.unescape(e[1]).gsub(/'/,"%27").gsub(/ /,"%20")+
"' target='"+target+"'><img src='"+e[2]+"' height='100px'></a>"
end
cgi.out{
images.join(" ")
}
end
end
``````

I use a little php program to return a random line (initial search phrase/word) from a given file:

``````
\$difficulty = 'easy';
if (isset(\$_GET['difficulty'])&&strlen(\$_GET['difficulty'])>0) {
\$difficulty= \$_GET['difficulty'];
}
\$word_list = 'nouns.txt';
\$possible_word_lists = array('nouns.txt','wiki.txt');
if (isset(\$_GET['word_list'])&&strlen(\$_GET['word_list'])>0) {
if(in_array(\$_GET['word_list'],\$possible_word_lists)){
\$word_list = \$_GET['word_list'];
}
}

\$query = "";
\$word_count = 1;
if(strcmp(\$word_list,'nouns.txt')==0){
if(strcmp(\$difficulty,"medium")==0){
\$word_count = 2;
}else if(strcmp(\$difficulty,"hard")==0){
\$word_count = 3;
}
}
for(\$i=0; \$i<\$word_count; \$i=\$i+1){
if(strlen(\$query)>0){
\$query= \$query."+";
}
\$query = \$query.`ruby -e "a=File.readlines('\$word_list').collect{|line| line.strip.gsub(' ','+').gsub('\'','%27')};puts a[rand*a.leng
\$query = trim(\$query);
}
print trim(\$query);
``````

As you can see, I gave up on php half way through and cheated by calling a ruby one-liner. Someday I'll fix this up...