[lnkForumImage]
TotalShareware - Download Free Software

Confronta i prezzi di migliaia di prodotti.
Asp Forum
 Home | Login | Register | Search 


 

Forums >

comp.lang.ruby

[QUIZ] Numbers Can Be Words (#133

James Gray

8/3/2007 1:01:00 PM

The three rules of Ruby Quiz:

1. Please do not post any solutions or spoiler discussion for this quiz until
48 hours have passed from the time on this message.

2. Support Ruby Quiz by submitting ideas as often as you can:

http://www.rub...

3. Enjoy!

Suggestion: A [QUIZ] in the subject of emails about the problem helps everyone
on Ruby Talk follow the discussion. Please reply to the original quiz message,
if you can.

-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=

by Morton Goldberg

When working with hexadecimal numbers it is likely that you've noticed some hex
numbers are also words. For example, 'bad' and 'face' are both English words and
valid hex numbers (2989 and 64206, respectively, in decimal). I got to thinking
that it would be interesting to find out how many and which hex numbers were
also valid English words. Of course, almost immediately I started to think of
generalizations. What about other bases? What about languages other than
English?

Your mission is to pick a word list in some language (it will have be one that
uses roman letters) and write Ruby code to filter the list to extract all the
words which are valid numbers in a given base. For many bases this isn't an
interesting task--for bases 2-10, the filter comes up empty; for bases 11-13,
the filter output is uninteresting (IMO); for bases approaching 36, the filter
passes almost everything (also uninteresting IMO). However, for bases in the
range from 14 to about 22, the results can be interesting and even surprising,
especially if one constrains the filter to accept only words of some length.

I used `/usr/share/dict/words` for my word list. Participants who don't have
that list on their system or want a different one can go to Kevin's Word List
Page (http://wordlist.source...) as a source of other word lists.

Some points you might want to consider: Do you want to omit short words like 'a'
and 'ad'? (I made word length a parameter). Do you want to allow capitalized
words (I prohibited them)? Do you want to restrict the bases allowed (I didn't)?

17 Answers

Karl von Laudermann

8/3/2007 1:20:00 PM

0

On Aug 3, 9:01 am, Ruby Quiz <ja...@grayproductions.net> wrote:
>
> When working with hexadecimal numbers it is likely that you've noticed some hex
> numbers are also words. For example, 'bad' and 'face' are both English words and
> valid hex numbers (2989 and 64206, respectively, in decimal). I got to thinking
> that it would be interesting to find out how many and which hex numbers were
> also valid English words. Of course, almost immediately I started to think of
> generalizations. What about other bases? What about languages other than
> English?

I'm not sure why this quiz is being phrased as "numbers that are
words". Aren't you just asking for a program that finds words that use
only the first n letters of the alphabet? Or am I missing something
obvious (tends to happen :-) )?

Actually, one interesting variant that would tie it to numbers would
be if you could include digits that look like letters, i.e.:
0 -> O
1 -> I
2 -> Z
5 -> S
6 -> G
8 -> B

In this case, even numbers in base 10 could be words.

James Gray

8/3/2007 1:38:00 PM

0

On Aug 3, 2007, at 8:20 AM, Karl von Laudermann wrote:

> On Aug 3, 9:01 am, Ruby Quiz <ja...@grayproductions.net> wrote:
>>
>> When working with hexadecimal numbers it is likely that you've
>> noticed some hex
>> numbers are also words. For example, 'bad' and 'face' are both
>> English words and
>> valid hex numbers (2989 and 64206, respectively, in decimal). I
>> got to thinking
>> that it would be interesting to find out how many and which hex
>> numbers were
>> also valid English words. Of course, almost immediately I started
>> to think of
>> generalizations. What about other bases? What about languages
>> other than
>> English?
>
> I'm not sure why this quiz is being phrased as "numbers that are
> words". Aren't you just asking for a program that finds words that use
> only the first n letters of the alphabet? Or am I missing something
> obvious (tends to happen :-) )?

That's pretty much the quiz, yes. It's not too hard to solve, but
the results are pretty interesting.

James Edward Gray II

Paul Novak

8/3/2007 1:46:00 PM

0

There is no end of numerological[0,1] variations that could be used by
anyone who feels the need for an additional challenge this week.

Regards,

Paul

[0] http://en.wikipedia.org/wiki/...
[1] http://en.wikipedia.org/wiki/Kabbalah#Number-Word...

Morton Goldberg

8/5/2007 3:56:00 PM

0

Here are some solutions to this quiz. The first solution deliberately
avoids using regular expressions. Note the use of next to skip over
words that are too short or capitalized and break to stop the
iteration when it gets into territory beyond where numbers of the
given base exist.

<code>
WORD_LIST = "/usr/share/dict/words"
WORDS = File.read(WORD_LIST).split

def number_words(base=16, min_letters=3)
result = []
WORDS.each do |w|
next if w.size < min_letters || (?A..?Z).include?(w[0])
break if w[0] > ?a + (base - 11)
result << w if w.to_i(base).to_s(base) == w
end
result
end
</code>

<example>
number_words(18, 5) # => ["abaca", "abaff", "accede", "achage",
"adage", "added", "adead", "aface", "ahead", "bacaba", "bacach",
"bacca", "baccae", "bache", "badge", "baggage", "bagged", "beach",
"beached", "beachhead", "beaded", "bebed", "bedad", "bedded",
"bedead", "bedeaf", "beech", "beedged", "beefhead", "beefheaded",
"beehead", "beeheaded", "begad", "behead", "behedge", "cabbage",
"cabbagehead", "cabda", "cache", "cadge", "caeca", "caffa", "caged",
"chafe", "chaff", "chebec", "cheecha", "dabba", "dagaba", "dagga",
"dahabeah", "deadhead", "debadge", "decad", "decade", "deedeed",
"deface", "degged", "dhabb", "echea", "edged", "efface", "egghead",
"facade", "faced", "faded", "fadge", "feedhead", "gabgab", "gadbee",
"gadded", "gadge", "gaffe", "gagee", "geggee", "hache", "haggada",
"hagged", "headache", "headed", "hedge"]
</example>

The second solution uses #inject rather than #each, but doesn't seem
to be much if any of an improvement. I found it interesting because
it's one of few times I've ever needed to pass an argument to break
and next.

<code>
WORD_LIST = "/usr/share/dict/words"
WORDS = File.read(WORD_LIST).split

def number_words(base=16, min_letters=3)
WORDS.inject([]) do |result, w|
next result if w.size < min_letters || (?A..?Z).include?(w[0])
break result if w[0] > ?a + (base - 11)
result << w if w.to_i(base).to_s(base) == w
result
end
end
</code>

<example>
number_words(20, 7) # => ["accidia", "accidie", "acidific",
"babiche", "bacchiac", "bacchic", "bacchii", "badiaga", "baggage",
"beached", "beachhead", "beedged", "beefhead", "beefheaded",
"beehead", "beeheaded", "behedge", "bighead", "cabbage",
"cabbagehead", "caddice", "caddiced", "caffeic", "cheecha",
"cicadid", "dahabeah", "deadhead", "debadge", "debeige", "decadic",
"decafid", "decided", "deedeed", "deicide", "diffide", "edifice",
"egghead", "feedhead", "giffgaff", "haggada", "haggadic", "headache",
"jibhead"]
</example>

In my third and last solution, I take the obvious route and use
regular expressions. Maybe regular expressions are better after all.

<code>
WORD_LIST = "/usr/share/dict/words"
WORDS = File.read(WORD_LIST).split

def number_words(base=16, min_letters=3)
biggest_digit = (?a + (base - 11))
regex = /\A[a-#{biggest_digit.chr}]+\z/
result = []
WORDS.each do |w|
next if w.size < min_letters || w =~ /^[A-Z]/
break if w[0] > biggest_digit
result << w if w =~ regex
end
result
end
</code>

The following are all the hex numbers in word list which have at
least three letters.

<example>
number_words # => ["aba", "abac", "abaca", "abaff", "abb", "abed",
"acca", "accede", "ace", "adad", "add", "adda", "added", "ade",
"adead", "aface", "affa", "baa", "baba", "babe", "bac", "bacaba",
"bacca", "baccae", "bad", "bade", "bae", "baff", "bead", "beaded",
"bebed", "bed", "bedad", "bedded", "bedead", "bedeaf", "bee", "beef",
"cab", "caba", "cabda", "cad", "cade", "caeca", "caffa", "cede",
"cee", "dab", "dabb", "dabba", "dace", "dad", "dada", "dade", "dae",
"daff", "dead", "deaf", "deb", "decad", "decade", "dee", "deed",
"deedeed", "deface", "ebb", "ecad", "edea", "efface", "facade",
"face", "faced", "fad", "fade", "faded", "fae", "faff", "fed", "fee",
"feed"]
</example>

Regards, Morton

Eugene Kalenkovich

8/5/2007 5:14:00 PM

0

"Ruby Quiz" <james@grayproductions.net> wrote in message > The three rules
of Ruby Quiz:
>
> by Morton Goldberg
>
> Your mission is to pick a word list in some language (it will have be one
> that
> uses roman letters) and write Ruby code to filter the list to extract all
> the
> words which are valid numbers in a given base. For many bases this isn't
> an
> interesting task--for bases 2-10, the filter comes up empty; for bases
> 11-13,
> the filter output is uninteresting (IMO); for bases approaching 36, the
> filter
> passes almost everything (also uninteresting IMO). However, for bases in
> the
> range from 14 to about 22, the results can be interesting and even
> surprising,
> especially if one constrains the filter to accept only words of some
> length.
>
Here are my 4 solutions :) (all use ?, so they will not work in 1.9)

# solution #1 - Simple one-liner

p File.read(ARGV[0]).split("\n").reject{|w| w !~
%r"^[a-#{(?a-11+ARGV[1].to_i).chr}]+$"}.sort_by{|w| [w.length,w]} if
(?a...?z)===?a-11+ARGV[1].to_i

# solution #2 - Non-hackery substs, like Olaf

p File.read(ARGV[0]).split("\n").reject{|w| w !~
%r"^[a-#{(?a-11+ARGV[1].to_i).chr}|lO]+$"}.sort_by{|w| [w.length,w]} if
(?a...?k)===?a-11+ARGV[1].to_i

# solution #3 - c001 hackerz

p File.read(ARGV[0]).split("\n").reject{|w| w !~
%r"^[a-#{(?a-11+ARGV[1].to_i).chr}|lo]+$"i}.map{|w|
w.downcase.gsub('o','0').gsub('l','1')}.sort_by{|w| [w.length,w]} if
(?a...?k)===?a-11+ARGV[1].to_i

# solution #4 - B16 5H0UT1N6 HACKER2

base=ARGV[1].to_i
base_=base+?a-11

raise "Bad base: [#{base}]" if base<1 || base_>?z

sub0=base_ < ?o
sub1=base>1 && base_ < ?l
sub2=base>2 && base_ < ?z
sub5=base>5 && base_ < ?s
sub6=base>6 && base_ < ?g
sub8=base>8 && base_ < ?b

reg="^["
reg<<'O' if sub0
reg<<'I' if sub1
reg<<'Z' if sub2
reg<<'S' if sub5
reg<<'G' if sub6
reg<<'B' if sub8
reg<<"|a-#{base_.chr}" if base>10
reg<<']+$'

result=File.read(ARGV[0]).split("\n").reject{|w| w !~ %r"#{reg}"i}.map{|w|
w.upcase}.sort_by{|w| [w.length,w]}
result.map!{|w| w.gsub('O','0')} if sub0
result.map!{|w| w.gsub('I','1')} if sub1
result.map!{|w| w.gsub('Z','2')} if sub2
result.map!{|w| w.gsub('S','5')} if sub5
result.map!{|w| w.gsub('G','6')} if sub6
result.map!{|w| w.gsub('B','8')} if sub8
result.reject!{|w| w !~ /[A-Z]/} # NUM8ER5-0NLY LIKE 61885 ARE N0T READA8LE
p result




Carl Porth

8/5/2007 5:33:00 PM

0

Just a simple regex, the rest is just option parsing.

#!/usr/bin/env ruby -wKU

require "optparse"

options = {
:base => 16,
:min_length => 1,
:word_file => "/usr/share/dict/words",
:case_insensitive => false
}

ARGV.options do |opts|
opts.banner = "Usage: #{File.basename($PROGRAM_NAME)} [OPTIONS]"

opts.separator ""
opts.separator "Specific Options:"

opts.on( "-b", "--base BASE", Integer,
"Specify base (default #{options[:base]})" ) do |base|
options[:base] = base
end

opts.on( "-l", "--min-word-length LENGTH", Integer,
"Specify minimum length" ) do |length|
options[:min_length] = length
end

opts.on( "-w", "--word-file FILE",
"Specify word file",
"(default #{options[:word_file]})" ) do |word_file|
options[:word_file] = word_file
end

opts.on( "-i", "--ignore-case",
"Ignore case distinctions in word file." ) do |i|
options[:ignore_case] = true
end

opts.separator "Common Options:"

opts.on( "-h", "--help",
"Show this message." ) do
puts opts
exit
end

begin
opts.parse!
rescue
puts opts
exit
end
end

last_letter = (options[:base] - 1).to_s(options[:base])
letters = ("a"..last_letter).to_a.join
exit if letters.size.zero?

criteria = Regexp.new("^[#{letters}]{#{options[:min_length]},}$",
options[:ignore_case])

open(options[:word_file]).each do |word|
puts word if word =~ criteria
end


On Aug 3, 6:01 am, Ruby Quiz <ja...@grayproductions.net> wrote:
> The three rules of Ruby Quiz:
>
> 1. Please do not post any solutions or spoiler discussion for this quiz until
> 48 hours have passed from the time on this message.
>
> 2. Support Ruby Quiz by submitting ideas as often as you can:
>
> http://www.rub...
>
> 3. Enjoy!
>
> Suggestion: A [QUIZ] in the subject of emails about the problem helps everyone
> on Ruby Talk follow the discussion. Please reply to the original quiz message,
> if you can.
>
> -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- =-=-=
>
> by Morton Goldberg
>
> When working with hexadecimal numbers it is likely that you've noticed some hex
> numbers are also words. For example, 'bad' and 'face' are both English words and
> valid hex numbers (2989 and 64206, respectively, in decimal). I got to thinking
> that it would be interesting to find out how many and which hex numbers were
> also valid English words. Of course, almost immediately I started to think of
> generalizations. What about other bases? What about languages other than
> English?
>
> Your mission is to pick a word list in some language (it will have be one that
> uses roman letters) and write Ruby code to filter the list to extract all the
> words which are valid numbers in a given base. For many bases this isn't an
> interesting task--for bases 2-10, the filter comes up empty; for bases 11-13,
> the filter output is uninteresting (IMO); for bases approaching 36, the filter
> passes almost everything (also uninteresting IMO). However, for bases in the
> range from 14 to about 22, the results can be interesting and even surprising,
> especially if one constrains the filter to accept only words of some length.
>
> I used `/usr/share/dict/words` for my word list. Participants who don't have
> that list on their system or want a different one can go to Kevin's Word List
> Page (http://wordlist.source...) as a source of other word lists.
>
> Some points you might want to consider: Do you want to omit short words like 'a'
> and 'ad'? (I made word length a parameter). Do you want to allow capitalized
> words (I prohibited them)? Do you want to restrict the bases allowed (I didn't)?


Ken Bloom

8/5/2007 5:42:00 PM

0

On Fri, 03 Aug 2007 13:46:16 +0000, Paul Novak wrote:

> There is no end of numerological[0,1] variations that could be used by
> anyone who feels the need for an additional challenge this week.

Well then, along those lines I have a Hebrew gematria counter. Give it
words on the commandline, and it will tell you what the gematria is of
those words, and what the total gematria.

I use this to check when converting Hebrew citations of Jewish books into
English for the benefit of those reading English newsgroups.

#!/usr/bin/env ruby
$KCODE = "u"
require "jcode"
require 'generator'
class String
def u_reverse; split(//).reverse.join; end
end

â?­LETTERVALUES=Hash.new(0).merge â?­ Hash['א' => 1, '×?' => 2, '×?' => 3, '×?' => 4, '×?' => 5,
â?­ '×?' => 6, '×?' => 7, '×?' => 8, '×?' => 9, '×?' => 10, '×?' => 20
â?­ '×?' => 30, '×?' => 40, '× ' => 50, 'ס' => 60, '×¢' => 70, 'פ' => 80,
� 'צ' => 90, 'ק' => 100, 'ר' => 200, 'ש' => 300, 'ת' => 400,
â?­ 'ם' => 40, '×?' => 20 , '×?' => 50, '×£' => 80, '×¥' => 90]
gematrias=ARGV.collect do |word|
word.split(//).inject(0) do |t,l|
t+LETTERVALUES[l]
end
end

SyncEnumerator.new(ARGV, gematrias).each do |word,value|
#reverse the word to print it RTL if all of the characters in it
#are hebrew letters

#note that this doesn't find nikudot, but then we don't care
#anyway because the terminal mangles nikudot -- the result will be
#so mangled anyway that we don't care whether it's reversed
word=word.u_reverse if word.split(//)-LETTERVALUES.keys==[]
printf "%s %d\n", word, value
end

printf "Total %d\n", gematrias.inject {|t,l| t+l}


--
Ken Bloom. PhD candidate. Linguistic Cognition Laboratory.
Department of Computer Science. Illinois Institute of Technology.
http://www.iit.edu...

James Gray

8/5/2007 10:59:00 PM

0

On Aug 5, 2007, at 10:46 AM, Raf Coremans wrote:

> I have come up with this one-liner:
>
> ----------8<----------
> puts File.readlines
> ('/usr/share/dict/words').grep(/\A[a-#{((b=ARGV[0].to_i)-1).to_s
> (b)}]+\Z/)
> ---------->8----------

I used a one-liner too:

ruby -sne 'print if $_.downcase =~ /\A[\d\s#{("a".."z").to_a.join[0...
($size.to_i - 10)]}]+\Z/' -- -size=12 /usr/share/dict/words

James Edward Gray II

Robert Klemme

8/6/2007 6:24:00 AM

0

My solution.

robert

dougal.s

8/6/2007 6:48:00 PM

0

Crude but effective.

Written in about 20minutes.

###################################################

@words = File.new('/usr/share/dict/words').read.downcase.scan(/[a-z]
+/).uniq
@chars = '0123456789abcdefghijklmnopqrstuvwxyz'

def print_matches(base,minsize=0)

print "Base: " + base.to_s + "\n"

alphabet = @chars[0,base]

print "Alphabet: " + alphabet + "\n\nMatching Words:\n\n"

@words.each do |w|

if w.length >= minsize
hexword = true
w.each_byte { |c|
if !alphabet.include?(c.chr)
hexword = false
break
end
}
p w if hexword
end
end

end

print_matches 18,4

#################################################

Output:

Base: 18
Alphabet: 0123456789abcdefgh

Matching Words:

"ababdeh"
"abac"
"abaca"
"abaff"
"abba"
"abed"
"acca"
"accede"
"achage"
"ache"
"adad"
"adage"
"adda"
"added"
"adead"
"aface"
"affa"
"agade"
"agag"
"aged"
"agee"
"agha"
...

Douglas F Shearer
http://douglasfs...