# Index and Query (#54)

**URL:** <https://www.ruby-forum.com/t/index-and-query-54/71342>\
**Category:** Ruby\
**Created:** [November 17, 2005, 7:06pm UTC](https://www.ruby-forum.com/t/index-and-query-54/71342 "2005-11-17T19:06:51Z")\
**Posts on this page:** 1\
**Page:** 1

<div class="post-metadata">

**Author:** ![zed.lopez](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/z/5e9695/32.png) [@zed.lopez](https://www.ruby-forum.com/u/zed.lopez)\
**Post date:** [November 17, 2005, 7:06pm UTC](https://www.ruby-forum.com/t/index-and-query-54/71342/1 "2005-11-17T19:06:51Z")

</div>

I’m a little late to the party. I just finished PickAxe2 and this is  
my first quiz (or Ruby program.) Mine doesn’t Marshal the data, but  
does offer both has\_any and has\_all methods.

class Lexicon

@@word\_index = {}  
@@i = -1

def initialize()  
@map = Hash.new(0)  
end

def add(doc,word)  
@@word\_index[word] = @@i+=1 unless @@word\_index.key?(word)  
@map[doc] |= bitmask(word)  
end

def has\_any(\*words)  
@map.keys.select {|k| (@map[k] & bitmask(words)) \> 0 }  
end

def has\_all(\*words)  
return [] if words.detect { |word| !@@word\_index.key?(word) }  
x = bitmask(words)  
@map.keys.select {|k| (@map[k] & x) == x }  
end

private

def bitmask(words)  
x = 0  
words.each {|word| x |= 1 \<\< @@word\_index[word] if  
@@word\_index.key?(word)}  
x  
end

end

index = Lexicon.new  
ARGF.each do |line|  
line.downcase.split.each { |word| index.add($FILENAME,word) }  
end

while words = $stdin.gets  
puts index.has\_all(\*words.split).join(’ ')  
end
