Never been to DZone Snippets before?

Snippets is a public source code repository. Easily build up your personal collection of code snippets, categorize them with tags / keywords, and share them with the world

About this user

« Newer Snippets
Older Snippets »
Showing 1-10 of 54 total  RSS 

Basic WEBrick setup for local web server

Put the following functions and aliases into your ~/.bash_login (or alternatives).


unset -f webrick_local

function webrick_local() { 

   declare root_dir="${HOME}/Desktop/www"

   /bin/mkdir -p "${root_dir}/WEBrickLog"
   /bin/chmod 0754 "${root_dir}" "${root_dir}/WEBrickLog"

   /usr/bin/touch "${root_dir}/WEBrickLog/webrick.pid" "${root_dir}/WEBrickLog/webrick_ruby.pid"
   /bin/chmod 0644 "${root_dir}/WEBrickLog/webrick.pid" "${root_dir}/WEBrickLog/webrick_ruby.pid"

#   /usr/bin/touch "${root_dir}/index.html"
#   /bin/chmod 0754 "${root_dir}/index.html"


/usr/local/bin/ruby <<-HEREDOC

   require 'webrick'
   require 'webrick/accesslog'
   include WEBrick

   require 'thread'
   require 'pp'

   root_dir = "${root_dir}"
   http_dir = File.expand_path(root_dir)

   File.open(http_dir + "/WEBrickLog/webrick_ruby.pid", "w") do |f|
      f.puts(Process.pid)
   end

   # cf. http://microjet.ath.cx/webrickguide/html/Logging.html
   webrick_log_file = File.expand_path(http_dir + "/WEBrickLog/webrick.log")
   #webrick_log_file = '/dev/null'  # disable logging
   webrick_logger = WEBrick::Log.new(webrick_log_file, WEBrick::Log::DEBUG)

   access_log_stream = webrick_logger
   access_log = [[ access_log_stream, WEBrick::AccessLog::COMBINED_LOG_FORMAT ]]

   system_mime_table = WEBrick::HTTPUtils::load_mime_types('/private/etc/httpd/mime.types.default')
   system_mime_table.store('rhtml', 'text/html')   # add a mime type for .rhtml files
   system_mime_table.store('php', 'text/html')
   system_mime_table.store('rb', 'text/plain')
   system_mime_table.store('pid', 'text/plain')
   #pp system_mime_table.sort_by { |k,v| k }

   server = WEBrick::HTTPServer.new(
     :BindAddress     =>    "localhost",
     :Port            =>    9090,
     :DocumentRoot    =>    http_dir,
     :FancyIndexing   =>    true,
     :MimeTypes       =>    system_mime_table,
     :Logger          =>    webrick_logger,
     :AccessLog       =>    access_log
   )

   server.config.store(:DirectoryIndex, server.config[:DirectoryIndex] << "default.htm")
   #pp server.config

   # cf. http://snippets.dzone.com/posts/show/5208
   class TimeServlet < HTTPServlet::AbstractServlet

      def do_GET(req, res)
         res['Content-Type'] = 'text/html'
         res.status = 200
         res.body = "<html>Time: #{Time.now.to_s}</html>" + "\n"
      end

      # cf. http://www.hiveminds.co.uk/node/244, published under the
      # GNU Free Documentation License, http://www.gnu.org/copyleft/fdl.html

      @@instance = nil
      @@instance_creation_mutex = Mutex.new

      def self.get_instance(config, *options)
         #pp @@instance
         @@instance_creation_mutex.synchronize { 
            @@instance = @@instance || self.new(config, *options) }
      end

   end


   # cf. http://ttripp.blogspot.com/2007/01/fun-with-http.html
   class PostDumper < WEBrick::HTTPServlet::AbstractServlet
  
      # Reload file for each request, instantly
      # updating the server with code changes 
      # without needing a restart.

=begin
      def PostDumper.get_instance( config, *options )
         load __FILE__
         PostDumper.new config, *options
      end
=end

      # cf. http://www.hiveminds.co.uk/node/244, published under the
      # GNU Free Documentation License, http://www.gnu.org/copyleft/fdl.html

      @@instance = nil
      @@instance_creation_mutex = Mutex.new

      def self.get_instance(config, *options)
         #pp @@instance
         @@instance_creation_mutex.synchronize { 
            @@instance = @@instance || self.new(config, *options) }
      end

      def do_GET( request, response )
         response.status = 200
         response['Content-Type'] = "text/plain"
         response.body = dump_request( request )
      end
  
      def do_POST( request, response )
         response.status = 200
         response['Content-Type'] = "text/plain"
         response.body = dump_request( request )
         response.body << request.body
      end
  
      def dump_request( request )
         request.request_line << "\r\n" <<
         request.raw_header.join( "" ) << "\r\n"
      end
   end

   server.mount("/dump", PostDumper)
   server.mount("/time", TimeServlet, {:FancyIndexing=>true})

   # handle signals
   %w(INT).each do |signal|
      trap(signal) { server.shutdown }
   end

   server.start

HEREDOC

return 0

}

export -f webrick_local

# start WEBrick alias
alias webrick='swr'

# start WEBrick
unset -f swr
function swr() {   
  declare webrick_pid_file="${HOME}/Desktop/www/WEBrickLog/webrick.pid"
  if [[ -e "${webrick_pid_file}" ]]; then echo "WEBrick already started!"; return 1; fi
  /bin/bash -c "webrick_local" &
  declare WEBRICKPID=$!
  mkdir -p "${HOME}/Desktop/www/WEBrickLog"
  echo $WEBRICKPID > "${HOME}/Desktop/www/WEBrickLog/webrick.pid"
  return 0
}
export -f swr

# quit WEBrick
unset -f qwr
function qwr() { 
   declare webrick_pid_file="${HOME}/Desktop/www/WEBrickLog/webrick.pid"
   declare webrick_ruby_pid_file="${HOME}/Desktop/www/WEBrickLog/webrick_ruby.pid"
   if [[ ! -e "${webrick_pid_file}" ]]; then echo "no such file: ${webrick_pid_file}"; return 1; fi
   declare PIDW=$(cat "${webrick_pid_file}" 2>/dev/null)
   declare PIDR=$(cat "${webrick_ruby_pid_file}" 2>/dev/null)
   kill -INT $PIDW 2>/dev/null || echo "no such PIDW: ${PIDW}"
   kill -INT $PIDR 2>/dev/null || echo "no such PIDR: ${PIDR}"
   rm -f "${webrick_pid_file}" "${webrick_ruby_pid_file}"
   return 0
}
export -f qwr

# quit WEBrick; cf. Job Control Commands, http://tldp.org/LDP/abs/html/x8816.html
###alias qwr='echo "quit WEBrick with ctrl-c ..."; fg %webrick 2>/dev/null'

alias openwww='/usr/bin/open http://localhost:9090'
alias wrlog='/usr/bin/open http://localhost:9090/WEBrickLog/webrick.log'


#----------------------------------------


source ~/.bash_login

webrick

openwww
wrlog
open http://localhost:9090 
open http://localhost:9090/WEBrickLog
open http://localhost:9090/WEBrickLog/webrick.log

open http://localhost:9090/time
open http://localhost:9090/dump

wrlog
qwr


Further information:

- WEBrick
- WEBrick RDoc
- What is WEBrick?
- Guide to using WEBrick for Rails development
- Dynamic WEBrick Servers in Ruby
- Gnome's Guide to WEBrick
- Running Servlets with WEBrick
- rsphandler
- URL rewriting with WEBrick

Binary radix trie in Ruby

# From: http://www.matasano.com/log/basic-uncommented-crappy-binary-radix-trie/
# Author: Thomas Ptacek
# cf. also http://www.matasano.com/log/1009/aguri-coolest-data-structure-youve-never-heard-of/

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

class Fixnum
    def to_b(l = 8)
        "0'" + self.to_s(2).rjust(l, "0")
    end
    def set?(i)
        if((self & (1 << i)) != 0)
            return true
        else
            return false
        end
    end

     def bdiff(x)
         ret = -1
         32.downto(0) do |i|
             if(self.set?(i) != x.set?(i))
                 ret = i
                 break
             end
         end
         ret
     end
end

class String
    def to_ip
        ip = 0
        split(".").each_with_index do |octet, index|
            ip |= (octet.to_i << ((3 - index)*8))
        end
        ip
    end
end

class SimpleTrie
    def initialize(width=32)
        @@node ||= Struct.new(:right, :left, :pos, :key, :value, :color)
        @root = @@node.new(nil, nil, width, 0, nil)
        @root.right = @root
        @root.left = @root
        @width = width
        @sz = 0
    end

    private

    def srch(key, limit=nil)
        cur = @root
        prev = nil

        while(((not prev) or (cur.pos < prev.pos)) and ((not limit) or cur.pos > limit))
            prev = cur
            if(key.set? cur.pos)
                cur = cur.right
            else
                cur = cur.left
            end
        end

        return cur, prev
    end

    public

    def []=(key, val)
        x, prev = srch(key)
        bit = key.bdiff(x.key)
        cur, prev = srch(key, bit)

        node = @@node.new(nil, nil, bit, key, val)

        if(key.set? bit)
            node.right = node
            node.left = cur
        else
            node.right = cur
            node.left = node
        end

        if(key.set? prev.pos)
            prev.right = node
        else
            prev.left = node
        end

        @sz += 1

        return val
    end

    def walk
        color = rand
        walker = lambda do |x, dir, tab|
            if(x.color != color)
                tab.times { print "  " }
                puts "#{ dir } #{ x.key } ( #{ x.key.to_b } ) @ #{ x.pos }"

                x.color = color

                walker.call(x.right, "-> ", tab+1)
                walker.call(x.left, "<- ", tab+1)
            end
        end

        walker.call(@root, ".   ", 0)
    end

    def [](key)
        res, p = srch(key)
        return res.value
    end
end


require 'pp'

t = SimpleTrie.new

t[3] = 3
t[4] = 4
t[2] = 2

t.walk
pp t

p t[3]

The Towers of Hanoi in Ruby

# based on: The shortest and "mysterious" TH algorithm,
# http://hanoitower.mkolar.org/shortestTHalgo.html
#
# Further references:
# - http://en.wikipedia.org/wiki/Tower_of_Hanoi
# - http://hanoitower.mkolar.org/HTonWebE.html
# - http://www.google.com/search?q=towers%20of%20hanoi%20Apostolos%20Syropoulos
# - http://www.kernelthread.com/hanoi/
# - http://www.kernelthread.com/hanoi/html/rb.html

n = 5 
x = 1

ar = []

start_time = Time.now

while x < (1 << n)
      fr=(x&x-1)%3;
      to=((x|x-1)+1)%3;
      ar.push(fr,to)
      puts "move from pole #{fr} to pole #{to}"
      x += 1
end

p ar

p Time.now - start_time

Basic Trie data structure in Ruby

# Inspired by http://www.rubyquiz.com/quiz103.html
# cf. also http://en.wikipedia.org/wiki/Trie

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

require 'pp'

class Hash

   def deep_merge!(second)
      # cf. http://snippets.dzone.com/posts/show/4146
      merger = proc { |key,v1,v2| Hash === v1 && Hash === v2 ? v1.merge(v2, &merger) : v2 }
      self.merge!(second, &merger)
   end

   def nested_hash(array)
      node = self
      array.each do |i|
         node[i]=Hash.new if node[i].nil?
         node = node[i]
      end 
      self
   end

   def merge_nested_hash!(nested_hash)
      deep_merge!(nested_hash)
   end

   # code basis taken from: "Find every path and it's value in a Hash" by Florian Aßmann,
   # http://snippets.dzone.com/posts/show/3565

   def each_trie_path
      raise ArgumentError unless block_given?
      self.class.each_trie_path(self) { |path, object| yield(path, object) }
   end

   protected
   def self.each_trie_path(object, path = [], &block)  

      if object.is_a?(Hash)
         object.each do |key, value|

            if key == true && value == {}
               if path == [:root]  # special case for empty string: [[:root], {true=>{}}]
                  yield(path, {true=>{}})
                  next
               end
               yield(path, object)
            end

            self.each_trie_path(value, [path , key].flatten, &block)
         end
      else 
         yield(path, object)
      end
   end 

end


class Trie

   @hash = Hash.new.merge_nested_hash!(Hash.new)
   #@hash = Hash.new.merge_nested_hash!({:root=>{}})
   #@hash = Hash.new.merge_nested_hash!(Hash.new.nested_hash([:root]))
   class << self; attr_accessor :hash; end    # Trie.hash

   def initialize
      Trie.hash.merge_nested_hash!({:root=>{}})
   end


   def add_int(int)   # for int >= 0
      ia = int.to_s.scan(/[[:digit:]]/).map { |i| i.to_i }  # integer array; ex: [4,6,2]
      ia.unshift(:root).push(true)
      Trie.hash.merge_nested_hash!(Hash.new.nested_hash(ia))
   end

   def matchi(int)  # match integer
      ia = int.to_s.scan(/[[:digit:]]/).map { |i| i.to_i }  
      node = Trie.hash.fetch(:root,nil)
      ia.each do |digit|
         node = node[digit]
         #node = node.fetch(digit,nil)
         return false unless node
      end
      node.fetch(true,nil) ? true : false
   end

   def mfpi(int)   # match first part of integer
      ia = int.to_s.scan(/[[:digit:]]/).map { |i| i.to_i }
      node = Trie.hash.fetch(:root,nil)
      ia.each do |digit|
         node = node[digit]
         return false unless node
      end
      return true
   end


   def add_word(word)
      ca = word.split(//u)    # UTF-8 aware character array
      ca.unshift(:root).push(true)
      Trie.hash.merge_nested_hash!(Hash.new.nested_hash(ca))
   end

   def match(word)   # match entire word
      ca = word.split(//u)    
      node = Trie.hash.fetch(:root,nil)
      ca.each do |char|
         node = node[char]
         #node = node.fetch(char,nil)
         return false unless node
      end
      node.fetch(true,nil) ? true : false
   end

   def mfpw(word)   # match first part of word
      ca = word.split(//u)    
      node = Trie.hash.fetch(:root,nil)
      ca.each do |char|
         node = node[char]
         return false unless node
      end
      return true
   end

end


trie = Trie.new
p Trie.hash

trie.add_word("word")
pp Trie.hash            
p trie.match("word")      
p trie.match("word2")   
trie.add_word("word2")
p trie.match("word2")   
pp Trie.hash            # {:root=>{"w"=>{"o"=>{"r"=>{"d"=>{true=>{}, "2"=>{true=>{}}}}}}}}

trie.add_word("")
p trie.match("")
pp Trie.hash

puts

p trie.match("word")      
p trie.mfpw("wor")     # match first part of word

puts

trie.add_int(12345)
p Trie.hash

trie.add_int(12980345)
pp Trie.hash

trie.add_int(8512)
pp Trie.hash
p trie.matchi(8512)
p trie.matchi(85)
p trie.mfpi(85)     # match first part of integer
p trie.matchi(51)

puts

puts
pp Trie.hash
paths = []
Trie.hash.each_trie_path { |path, value| paths.push([ path ]) }
#Trie.hash.each_trie_path { |path, value| paths.push([ path, value ]) }
#pp paths
puts
paths.each { |x| p x }
puts


#------------------------------------------------------


require 'pp'

class Hash
   def Hash.new_nested_hash
     Hash.new{|h,k| h[k]=Hash.new(&h.default_proc) }
   end
end


class Trie

   @hash = Hash.new_nested_hash
   #@hash = Hash.new_nested_hash.update(true=>{})  # add empty string by default
   class << self; attr_accessor :hash; end    # Trie.hash

   def <<(word)
      ca = word.split(//u)    # UTF-8 aware character array
      wl = ca.size            # word length
      str = ""
      wl.times { |x| str << "[ca.at(#{x})]" }
      str = "Trie.hash" << str << "[true]"
      #p str     # example: "Trie.hash[ca.at(0)][ca.at(1)][ca.at(2)][ca.at(3)][true]"
      eval(str)
   end


   def match(word)
      ca = word.split(//u)    # UTF-8 aware character array
      wl = ca.size            # word length
      str = ""

      wl.times { |x| str << ".fetch(ca.at(#{x}),nil)" }
      str = "Trie.hash" << str << ".fetch(true,nil)"
      #p str   # example: "Trie.hash.fetch(ca.at(0),nil).fetch(ca.at(1),nil).fetch(ca.at(2),nil).fetch(true,nil)"
      ret = eval(str) rescue nil

=begin
      # alternative
      wl.times { |x| str << ".fetch(ca.at(#{x}),{})" }
      str = "Trie.hash" << str << ".fetch(true,nil)"
      #p str   # example: "Trie.hash.fetch(ca.at(0),{}).fetch(ca.at(1),{}).fetch(ca.at(2),{}).fetch(true,nil)"
      ret = eval(str)
=end

      ret == {} ? true : false   # {} is the default value created by Trie.hash or Hash.new_nested_hash respectively
   end

end


trie = Trie.new
trie << "word"
pp Trie.hash            
p trie.match("word")      
p trie.match("word2")   
trie << "word2"
p trie.match("word2")   
pp Trie.hash            # {"w"=>{"o"=>{"r"=>{"d"=>{true=>{}, "2"=>{true=>{}}}}}}}

trie << ""
p trie.match("")
pp Trie.hash


#------------------------------------------


# alternative with default :root element

require 'pp'

class Hash
   def Hash.new_nested_hash
     Hash.new{|h,k| h[k]=Hash.new(&h.default_proc) }
   end
end


class Hash

   # code basis taken from: "Find every path and it's value in a Hash" by Florian Aßmann,
   # http://snippets.dzone.com/posts/show/3565

   def each_trie_path
      raise ArgumentError unless block_given?
      self.class.each_trie_path(self) { |path, object| yield(path, object) }
   end

   protected
   def self.each_trie_path(object, path = [], &block)  

      if object.is_a?(Hash)
         object.each do |key, value|

            if key == true && value == {}
               if path == [:root]  # special case for empty string: [[:root], {true=>{}}]
                  yield(path, {true=>{}})
                  next
               end
               yield(path, object)
            end

            self.each_trie_path(value, [path , key].flatten, &block)
         end
      else 
         yield(path, object)
      end
   end 

end


class Trie

   @hash = Hash.new_nested_hash
   class << self; attr_accessor :hash; end    # Trie.hash

   def initialize
      Trie.hash[:root]
   end


   def add_int(int)   # for int >= 0
      ia = int.to_s.scan(/[[:digit:]]/).map { |i| i.to_i }  # integer array; ex: [4,6,2]
      ia.unshift(:root)
      str = ""
      ia.size.times { |x| str << "[ia.at(#{x})]" }
      str = "Trie.hash" << str << "[true]"
      eval(str)
   end

   def matchi(int)  # match integer
      ia = int.to_s.scan(/[[:digit:]]/).map { |i| i.to_i }  
      node = Trie.hash.fetch(:root,nil)
      ia.each do |digit|
         node = node.fetch(digit,nil)
         return false unless node
      end
      node.fetch(true,nil) ? true : false
   end

   def mfpi(int)   # match first part of integer
      ia = int.to_s.scan(/[[:digit:]]/).map { |i| i.to_i }
      node = Trie.hash.fetch(:root,nil)
      ia.each do |digit|
         node = node.fetch(digit,nil)
         return false unless node
      end
      return true
   end


   def <<(word)
      ca = word.split(//u)    # UTF-8 aware character array
      ca.unshift(:root)
      #ca = [:root, *word.split(//u)]
      #ca = [:root].concat(word.split(//u))
      str = ""
      ca.size.times { |x| str << "[ca.at(#{x})]" }
      str = "Trie.hash" << str << "[true]"
      #p str     # example: "Trie.hash[ca.at(0)][ca.at(1)][ca.at(2)][ca.at(3)][true]"
      eval(str)
   end

   def match(word)
      ca = word.split(//u)    
      ca.unshift(:root)
      #ca = [:root, *word.split(//u)]
      #ca = [:root].concat(word.split(//u))
      str = ""
      ca.size.times { |x| str << ".fetch(ca.at(#{x}),nil)" }
      str = "Trie.hash" << str << ".fetch(true,nil)"
      #p str   # example: "Trie.hash.fetch(ca.at(0),nil).fetch(ca.at(1),nil).fetch(ca.at(2),nil).fetch(true,nil)"
      ret = eval(str) rescue nil

=begin
      # alternative
      ca.size.times { |x| str << ".fetch(ca.at(#{x}),{})" }
      str = "Trie.hash" << str << ".fetch(true,nil)"
      #p str   # example: "Trie.hash.fetch(ca.at(0),{}).fetch(ca.at(1),{}).fetch(ca.at(2),{}).fetch(true,nil)"
      ret = eval(str)
=end

      ret == {} ? true : false   # {} is the default value created by Trie.hash or Hash.new_nested_hash respectively
   end

   def match2(word)   # match entire word
      ca = word.split(//u)    
      node = Trie.hash.fetch(:root,nil)
      ca.each do |char|
         node = node.fetch(char,nil)
         return false unless node
      end
      node.fetch(true,nil) ? true : false
   end

   def mfpw(word)   # match first part of word
      ca = word.split(//u)    
      node = Trie.hash.fetch(:root,nil)
      ca.each do |char|
         node = node.fetch(char,nil)
         return false unless node
      end
      return true
   end

end


trie = Trie.new
trie << "word"
pp Trie.hash            
p trie.match("word")      
p trie.match("word2")   
trie << "word2"
p trie.match("word2")   
pp Trie.hash            # {:root=>{"w"=>{"o"=>{"r"=>{"d"=>{true=>{}, "2"=>{true=>{}}}}}}}}

trie << ""
p trie.match("")
pp Trie.hash

puts

p trie.match2("word")      
p trie.mfpw("wor")     # match first part of word

puts

trie.add_int(8512)
pp Trie.hash
p trie.matchi(8512)
p trie.matchi(85)
p trie.mfpi(85)     # match first part of integer
p trie.matchi(51)

puts

puts
pp Trie.hash
paths = []
Trie.hash.each_trie_path { |path, value| paths.push([ path ]) }
#Trie.hash.each_trie_path { |path, value| paths.push([ path, value ]) }
#pp paths
puts
paths.each { |x| p x }
puts

Anagram finder in Ruby

# first create a word list file at /Users/Shared/words:
mkdir -p /Users/Shared
sudo chmod 1777 /Users/Shared
sudo cp /usr/share/dict/words /Users/Shared/words
sudo chown $(logname):$(logname) /Users/Shared/words
sudo chmod 666 /Users/Shared/words
# or
cd /Users/Shared
curl -L -o words http://pragdave.pragprog.com/data/wordlist.txt


#---------------------------------------------


# cat anagram.rb

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

# Based on:
# Solving Anagrams in Ruby,
# http://lojic.com/blog/2007/10/22/solving-anagrams-in-ruby/
# Author: Brian Adkins

word_list_file = "/Users/Shared/words"
word_hash_file = "/Users/Shared/word_hash"

exit 1 unless File.exist?(word_list_file)

1.times do

   if not File.exist?(File.expand_path(word_hash_file))

      words = Hash.new([])

      File.open(word_list_file).each_line do |w| 
         w = w.chomp

         # create a hash with sorted letters as keys and words as values
         # example: "alst" => ["last", "salt", "slat"]

         word = w.downcase
         sorted_word = word.split('').sort!.join('').delete(" ")
         words[sorted_word] |= [w]    # |= makes sure array elements in [w] are unique

      end

      #words.each_pair { |k,v| puts "#{k.inspect} => #{v.inspect}" if v.size > 2 }
      #words.each_value { |v| p v if v.size > 2 }
      #p words.sort_by {|k, v| v.size }.last  # largest anagram set

      File.open(File.expand_path(word_hash_file), "w") do |file|
         Marshal.dump(words, file)
      end

      redo

   else

      words = nil

      File.open(File.expand_path(word_hash_file), "r") do |file|
         words = Marshal.load(file)
      end

      while true
         print "Enter word: "
         anagram = gets.chomp
         exit 0 if anagram == "exit"
         anagram = anagram.downcase
         sorted_anagram = anagram.split('').sort!.join('').delete(" ")
         p words[sorted_anagram]
      end

   end

end


#---------------------------


# adding new words to the word_hash file from the command line:
rm -f /Users/Shared/word_hash
function add_words() { printf "%s\n" "$@" >> /Users/Shared/words; }
add_words London "New York"
# ... and then run anagram.rb again

Simple irb prompt


# cf. http://www.ruby-forum.com/topic/99818 and http://www.ruby-forum.com/topic/84414

# put the following lines into ~/.irbrc

# Tab completion
require 'irb/completion'
IRB.conf[:USE_READLINE]