[lnkForumImage]
TotalShareware - Download Free Software

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


 

Forums >

comp.lang.ruby

[QUIZ] Goedel (#147

James Gray

11/16/2007 7:44: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 Hugh Sasse

In the book "Starburst" by Frederik Pohl ISBN 0-345-27537-3, page 56, without
really spoiling the plot, some characters complain about the verbosity of
communications and encode a message by Gödelizing it (detailed on page 58).

The encoding works by taking each successive character of a message and raising
each successive prime to some function of that character, and multiplying these
powers of primes together. So for example we could use the ASCII code + 1 to
allow for nulls to be encoded. Then "Ruby\r\n" would end up as:

(2 ** R) * (3 ** u) * (5 ** b)....

10992805522291106558517740012022207329045811217010725353610920778
28664749233402453985379760678149866991742205982820039955872246774
86029159248495553882158351479922840433375701904296875000000000000
00000000000000000000000000000000000000000000000000000000000000000
000000

The idea is partly to obscure the message by the amount of factorization needed.
This quiz is to write a program to Gödelize a message, and a program to
deGödelize it.

The funtion used to map characters described in the book is "A" => 1, "B" => 2,
etc and an example is given where spaces are 0. Nothing further is said about
punctuation, or lower case. The message sent in the book is:

msg = (3.875 * (12 ** 26)) +
(1973 ** 854) + (331 ** 852) +
(17 ** 2008) + (3 ** 9707) + (2 ** 88) - 78

which it turns out has lots of 0 powers in it, so I strictly don't need the
ASCII + 1 I've used in my example, I could use just ASCII, and the nulls would
not increase the size of the resulting number. This further means that if a list
of characters is sent in decreasing frequency order with the message, the most
frequent could be encoded as 0 and the number would be that much smaller. In
English it is likely to be an "e" or " " which ends up coded as 0.

Interesting things arising from this:

1 Finding the power once a prime is selected
2 Getting the list of primes in the first place
3 encoding of characters, as mentioned above
4 representing the number that results from encoding.

19 Answers

James Gray

11/16/2007 7:48:00 PM

0

On Nov 16, 2007, at 1:43 PM, Ruby Quiz wrote:

> by Hugh Sasse
>
> In the book "Starburst" by Frederik Pohl ISBN 0-345-27537-3, page =20
> 56, without really spoiling the plot, some characters complain =20
> about the verbosity of communications and encode a message by =20
> G=F6delizing it (detailed on page 58).

This quiz will run for two weeks because of the holiday. The no-=20
spoiler period is still the normal 48 hours.

James Edward Gray II=

Eric I.

11/17/2007 1:18:00 AM

0

> The encoding works by taking each successive character of a message and raising
> each successive prime to some function of that character, and multiplying these
> powers of primes together. So for example we could use the ASCII code + 1 to
> allow for nulls to be encoded. Then "Ruby\r\n" would end up as:
>
> (2 ** R) * (3 ** u) * (5 ** b)....
>
> 10992805522291106558517740012022207329045811217010725353610920778
> 28664749233402453985379760678149866991742205982820039955872246774
> 86029159248495553882158351479922840433375701904296875000000000000
> 00000000000000000000000000000000000000000000000000000000000000000
> 000000

If I'm not mistaken, the number given is the encoding for "Ruby\n".
The encoding for "Ruby\r\n" is:


26221858870290182364639031466277185911546960210395902825153752677

86758380406769132705749108355204343696163662611760821989161975619

72000918860271223092350554891796472401033816989022830694122314453

12500000000000000000000000000000000000000000000000000000000000000
000000000000000000000

Eric

James Gray

11/17/2007 3:28:00 AM

0

On Nov 16, 2007, at 7:20 PM, Eric I. wrote:

>> The encoding works by taking each successive character of a
>> message and raising
>> each successive prime to some function of that character, and
>> multiplying these
>> powers of primes together. So for example we could use the ASCII
>> code + 1 to
>> allow for nulls to be encoded. Then "Ruby\r\n" would end up as:
>>
>> (2 ** R) * (3 ** u) * (5 ** b)....
>>
>>
>> 10992805522291106558517740012022207329045811217010725353610920778
>>
>> 28664749233402453985379760678149866991742205982820039955872246774
>>
>> 86029159248495553882158351479922840433375701904296875000000000000
>>
>> 00000000000000000000000000000000000000000000000000000000000000000
>> 000000
>
> If I'm not mistaken, the number given is the encoding for "Ruby\n".

Yeah, I think you are right. I've updated the quiz page.

James Edward Gray II

steve d

11/18/2007 7:51:00 PM

0

Here's my submission:

http://pastie.caboo...

class String
def godelize
prime =3D 0 ; product =3D 1
each_byte do |b|
product *=3D (prime =3D prime.next_prime) ** (b+1)
end

product
end

def self.from_godel(godel_integer)
str =3D ""
$stdout.sync =3D true
godel_integer.to_i.factorize.sort_by{|factor, value|factor}.each do
|factor, value|
str << (value-1).chr
end

str
end
end

class Integer
def next_prime
n =3D self
true while !(n+=3D1).prime?

n
end

def prime?
return false if [0,1].include? self.abs

return false if self > 2 and self%2 =3D=3D 0
(3..self/2).step(2) do |n|
return false if self%n =3D=3D 0
end

true
end

def factorize
factors =3D {} ; prime =3D 0 ; n =3D self

while n >=3D prime
prime =3D prime.next_prime
count =3D count_factor(prime)

if count > 0
factors[prime] =3D count
n /=3D prime**count
end
end

factors
end

def count_factor(f)
return 0 if self % f !=3D 0

cnt =3D 1 ; n =3D self

cnt +=3D 1 while (n/=3Df) % f =3D=3D 0

cnt
end
end


if $0 =3D=3D __FILE__
case ARGV.shift
when /--encode/
puts STDIN.read.godelize.to_s(36)
when /--decode/
puts String.from_godel(STDIN.read.to_i(36))
end
end

run it with: *ruby godelize.rb --encode* or *ruby godelize.rb --decode*
it uses stdin/stdout for input/output

it outputs the number in base 36 as a very simple way to reduce the size a
bit

- steve


On Nov 17, 2007 2:43 AM, Ruby Quiz <james@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.
>
>
> -=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D-=
=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D=
-=3D-=3D-=3D
>
> by Hugh Sasse
>
> In the book "Starburst" by Frederik Pohl ISBN 0-345-27537-3, page 56,
> without
> really spoiling the plot, some characters complain about the verbosity of
> communications and encode a message by G=F6delizing it (detailed on page
> 58).
>
> The encoding works by taking each successive character of a message and
> raising
> each successive prime to some function of that character, and multiplying
> these
> powers of primes together. So for example we could use the ASCII code + 1
> to
> allow for nulls to be encoded. Then "Ruby\r\n" would end up as:
>
> (2 ** R) * (3 ** u) * (5 ** b)....
>
> 10992805522291106558517740012022207329045811217010725353610920778
> 28664749233402453985379760678149866991742205982820039955872246774
> 86029159248495553882158351479922840433375701904296875000000000000
> 00000000000000000000000000000000000000000000000000000000000000000
> 000000
>
> The idea is partly to obscure the message by the amount of factorization
> needed.
> This quiz is to write a program to G=F6delize a message, and a program to
> deG=F6delize it.
>
> The funtion used to map characters described in the book is "A" =3D> 1, "=
B"
> =3D> 2,
> etc and an example is given where spaces are 0. Nothing further is said
> about
> punctuation, or lower case. The message sent in the book is:
>
> msg =3D (3.875 * (12 ** 26)) +
> (1973 ** 854) + (331 ** 852) +
> (17 ** 2008) + (3 ** 9707) + (2 ** 88) - 78
>
> which it turns out has lots of 0 powers in it, so I strictly don't need
> the
> ASCII + 1 I've used in my example, I could use just ASCII, and the nulls
> would
> not increase the size of the resulting number. This further means that if
> a list
> of characters is sent in decreasing frequency order with the message, the
> most
> frequent could be encoded as 0 and the number would be that much smaller.
> In
> English it is likely to be an "e" or " " which ends up coded as 0.
>
> Interesting things arising from this:
>
> 1 Finding the power once a prime is selected
> 2 Getting the list of primes in the first place
> 3 encoding of characters, as mentioned above
> 4 representing the number that results from encoding.
>
>

lavigne.eric@gmail.com

11/18/2007 7:55:00 PM

0

My solution follows. I would have liked the Prime class to have a
"this" method that would allow me to get the most recently returned
prime number again, as that would have shaved a line off. My goals
were to keep the Encryption class short and stateless, so please let
me know if you see ways to shorten it further.

# code begins

require 'mathn'

class Encryption
=09def Encryption.encode(msg,primes=3DPrime.new)
=09=09return 1 if msg.size.zero?
=09=09return (primes.succ ** (1 + msg[0])) * encode(msg.slice(1,msg.size),p=
rimes)
=09end
=09def Encryption.decode(num,primes=3DPrime.new)
=09=09return "" unless num > 1
=09=09prime =3D primes.next
=09=09multiplicity =3D factor_multiplicity(prime,num)
=09=09(multiplicity-1).chr + Encryption.decode(num / (prime **
multiplicity), primes)
=09end
=09private
=09def Encryption.factor_multiplicity(factor,num)
=09=091.upto(num) {|x| return x - 1 unless num.modulo(factor**x).zero?}
=09end
end

puts "Test encoding: "+Encryption.encode("Ruby\n").to_s+"\n"
puts "Test decoding: "+Encryption.decode(Encryption.encode("Ruby\n"))+"\n"

# code ends

On Nov 16, 2007 2:43 PM, Ruby Quiz <james@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 ev=
eryone
> on Ruby Talk follow the discussion. Please reply to the original quiz me=
ssage,
> if you can.
>
> -=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D-=
=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D=
-=3D-=3D-=3D
>
> by Hugh Sasse
>
> In the book "Starburst" by Frederik Pohl ISBN 0-345-27537-3, page 56, wit=
hout
> really spoiling the plot, some characters complain about the verbosity of
> communications and encode a message by G=F6delizing it (detailed on page =
58).
>
> The encoding works by taking each successive character of a message and r=
aising
> each successive prime to some function of that character, and multiplying=
these
> powers of primes together. So for example we could use the ASCII code + 1=
to
> allow for nulls to be encoded. Then "Ruby\r\n" would end up as:
>
> (2 ** R) * (3 ** u) * (5 ** b)....
>
> 10992805522291106558517740012022207329045811217010725353610920778
> 28664749233402453985379760678149866991742205982820039955872246774
> 86029159248495553882158351479922840433375701904296875000000000000
> 00000000000000000000000000000000000000000000000000000000000000000
> 000000
>
> The idea is partly to obscure the message by the amount of factorization =
needed.
> This quiz is to write a program to G=F6delize a message, and a program to
> deG=F6delize it.
>
> The funtion used to map characters described in the book is "A" =3D> 1, "=
B" =3D> 2,
> etc and an example is given where spaces are 0. Nothing further is said a=
bout
> punctuation, or lower case. The message sent in the book is:
>
> msg =3D (3.875 * (12 ** 26)) +
> (1973 ** 854) + (331 ** 852) +
> (17 ** 2008) + (3 ** 9707) + (2 ** 88) - 78
>
> which it turns out has lots of 0 powers in it, so I strictly don't need t=
he
> ASCII + 1 I've used in my example, I could use just ASCII, and the nulls =
would
> not increase the size of the resulting number. This further means that if=
a list
> of characters is sent in decreasing frequency order with the message, the=
most
> frequent could be encoded as 0 and the number would be that much smaller.=
In
> English it is likely to be an "e" or " " which ends up coded as 0.
>
> Interesting things arising from this:
>
> 1 Finding the power once a prime is selected
> 2 Getting the list of primes in the first place
> 3 encoding of characters, as mentioned above
> 4 representing the number that results from encoding.
>
>



--=20
There are two ways of constructing a software design: One way is to
make it so simple that there are obviously no deficiencies, and the
other way is to make it so complicated that there are no obvious
deficiencies. The first method is far more difficult.

- C.A.R. Hoare -

steve d

11/18/2007 8:43:00 PM

0

there's an instance var @primes which has the list of already generated
primes, @primes.last would do it

On Nov 19, 2007 2:54 AM, Eric Lavigne <lavigne.eric@gmail.com> wrote:

> My solution follows. I would have liked the Prime class to have a
> "this" method that would allow me to get the most recently returned
> prime number again, as that would have shaved a line off. My goals
> were to keep the Encryption class short and stateless, so please let
> me know if you see ways to shorten it further.
>
> # code begins
>
> require 'mathn'
>
> class Encryption
> def Encryption.encode(msg,primes=3DPrime.new)
> return 1 if msg.size.zero?
> return (primes.succ ** (1 + msg[0])) * encode(msg.slice(1,
> msg.size),primes)
> end
> def Encryption.decode(num,primes=3DPrime.new)
> return "" unless num > 1
> prime =3D primes.next
> multiplicity =3D factor_multiplicity(prime,num)
> (multiplicity-1).chr + Encryption.decode(num / (prime **
> multiplicity), primes)
> end
> private
> def Encryption.factor_multiplicity(factor,num)
> 1.upto(num) {|x| return x - 1 unless num.modulo
> (factor**x).zero?}
> end
> end
>
> puts "Test encoding: "+Encryption.encode("Ruby\n").to_s+"\n"
> puts "Test decoding: "+Encryption.decode(Encryption.encode("Ruby\n"))+"\n=
"
>
> # code ends
>
> On Nov 16, 2007 2:43 PM, Ruby Quiz <james@grayproductions.net> wrote:
> > The three rules of Ruby Quiz:
> >
> > 1. Please do not post any solutions or spoiler discussion for this qui=
z
> 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.
> >
> >
> -=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D-=
=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D=
-=3D-=3D-=3D
> >
> > by Hugh Sasse
> >
> > In the book "Starburst" by Frederik Pohl ISBN 0-345-27537-3, page 56,
> without
> > really spoiling the plot, some characters complain about the verbosity
> of
> > communications and encode a message by G=F6delizing it (detailed on pag=
e
> 58).
> >
> > The encoding works by taking each successive character of a message and
> raising
> > each successive prime to some function of that character, and
> multiplying these
> > powers of primes together. So for example we could use the ASCII code +
> 1 to
> > allow for nulls to be encoded. Then "Ruby\r\n" would end up as:
> >
> > (2 ** R) * (3 ** u) * (5 ** b)....
> >
> >
> 10992805522291106558517740012022207329045811217010725353610920778
> >
> 28664749233402453985379760678149866991742205982820039955872246774
> >
> 86029159248495553882158351479922840433375701904296875000000000000
> >
> 00000000000000000000000000000000000000000000000000000000000000000
> > 000000
> >
> > The idea is partly to obscure the message by the amount of factorizatio=
n
> needed.
> > This quiz is to write a program to G=F6delize a message, and a program =
to
> > deG=F6delize it.
> >
> > The funtion used to map characters described in the book is "A" =3D> 1,
> "B" =3D> 2,
> > etc and an example is given where spaces are 0. Nothing further is said
> about
> > punctuation, or lower case. The message sent in the book is:
> >
> > msg =3D (3.875 * (12 ** 26)) +
> > (1973 ** 854) + (331 ** 852) +
> > (17 ** 2008) + (3 ** 9707) + (2 ** 88) - 78
> >
> > which it turns out has lots of 0 powers in it, so I strictly don't need
> the
> > ASCII + 1 I've used in my example, I could use just ASCII, and the null=
s
> would
> > not increase the size of the resulting number. This further means that
> if a list
> > of characters is sent in decreasing frequency order with the message,
> the most
> > frequent could be encoded as 0 and the number would be that much
> smaller. In
> > English it is likely to be an "e" or " " which ends up coded as 0.
> >
> > Interesting things arising from this:
> >
> > 1 Finding the power once a prime is selected
> > 2 Getting the list of primes in the first place
> > 3 encoding of characters, as mentioned above
> > 4 representing the number that results from encoding.
> >
> >
>
>
>
> --
> There are two ways of constructing a software design: One way is to
> make it so simple that there are obviously no deficiencies, and the
> other way is to make it so complicated that there are no obvious
> deficiencies. The first method is far more difficult.
>
> - C.A.R. Hoare -
>
>

lavigne.eric@gmail.com

11/18/2007 8:50:00 PM

0

On Nov 18, 2007 2:50 PM, steve <oksteev@yahoo.com> wrote:
> Here's my submission:
>
> http://pastie.caboo...
>
> class String
> def godelize
> prime = 0 ; product = 1
> each_byte do |b|
> product *= (prime = prime.next_prime) ** (b+1)
> end
>
> product
> end
>
> def self.from_godel(godel_integer)

I learned about the "self" keyword and adding methods to existing
classes by reading Steve's submission. I modified my own submission to
use these. It is now slightly shorter and significantly easier to use.

# code begins

require 'mathn'

class String
def to_godel(primes=Prime.new)
return 1 if size.zero?
return (primes.succ ** (1 + self[0])) * slice(1,size).to_godel(primes)
end
def self.from_godel(num,primes=Prime.new)
return "" unless num > 1
prime = primes.next
multiplicity = factor_multiplicity(prime,num)
(multiplicity-1).chr + from_godel(num / (prime ** multiplicity), primes)
end
private
def self.factor_multiplicity(factor,num)
1.upto(num) {|x| return x - 1 unless num.modulo(factor**x).zero?}
end
end

puts "Test encoding: "+"Ruby\n".to_godel.to_s+"\n"
puts "Test decoding: "+String.from_godel("Ruby\n".to_godel)+"\n"

# code ends

--
There are two ways of constructing a software design: One way is to
make it so simple that there are obviously no deficiencies, and the
other way is to make it so complicated that there are no obvious
deficiencies. The first method is far more difficult.

- C.A.R. Hoare -

lavigne.eric@gmail.com

11/18/2007 9:08:00 PM

0

On Nov 18, 2007 3:42 PM, steve <oksteev@yahoo.com> wrote:
> there's an instance var @primes which has the list of already generated
> primes, @primes.last would do it
>

Sounds simple enough, but accessing instance variables seems to be a
rather verbose operation.

Here is what it should look like (if the Prime class worked the way I
originally expected):
primes = Prime.new
primes.next.doSomething
primes.last.doSomethingElse

Here was my first attempt using your suggestion, which looks
reasonable but doesn't work.
primes = Prime.new
primes.next.doSomething
primes.@primes.last.doSomethingElse

Here is what finally worked, but I can't believe the verbosity of the
final line. Is there a shorter way?
primes = Prime.new
primes.next.doSomething
primes.instance_variable_get("@primes").last.doSomethingElse


--
There are two ways of constructing a software design: One way is to
make it so simple that there are obviously no deficiencies, and the
other way is to make it so complicated that there are no obvious
deficiencies. The first method is far more difficult.

- C.A.R. Hoare -

Eric I.

11/19/2007 1:37:00 AM

0

I wanted to make an effort at runtime efficiency. This is
particularly important when trying to decode the message. For
example, if the value encoded with the current prime (p) is "d", then
the factor is p**101. The slow way would be to divide the current
Goedel value by p 102 times (101 times, and then the 102nd fails).
But you could also try dividing it by p**64, p**32, p**16, p**8, p**4,
p**2, and p**1. You would find that it does divide by p**64, p**32,
p**4, and p**1 without a remainder, and 64 + 32 + 4 + 1 == 101.

So as long as all the encoded values are less than 128 (which handles
all printable ascii values), you would have to divide the current
Goedel value only 7 times for each character decoded. Since I imagine
most characters would be lower-case letters, they would require on the
order of 100+ divisions using the slower method.

For an additional efficiency note that prime**2 is prime squared. And
prime**4 is prime**2 squared. And so forth. So we can generate all
the factors we want to try by successive squaring, which is probably
more efficient than calculating prime**64 separately from prime**32.
The problem is we have to first divide by prime**64, so we can
generate and store all the factors in an array, and try dividing from
the largest down to the smallest.

Eric

====

require 'mathn' # for Prime class


# Put the coder in a separate class, so we have the potential to use
# other coders, such as the one from the Starburst novel.
class RubyQuizCoder
def encode(char)
char[0] + 1
end

def decode(number)
(number - 1).chr
end

def max_code
127
end
end


def encode(input, primes, coder)
goedel_value = 1

input.each_line do |line|
0.upto(line.size - 1) do |i|
char = line[i, 1]
encoding = coder.encode char
next if encoding.nil? # skip characters without encoding
goedel_value *= primes.next ** encoding
end
end

puts goedel_value
end


# Attempt to decode quickly by trying to perfectly divide by
# prime**(2**6), prime**(2**5), prime**(2**4), ..., prime**(2**0) and
# then adding the powers of 2 for which the division worked without a
# remainder. For example, if a number were divisible by prime**101,
# then it's also divisible by prime**64 * prime**32 * prime**4 *
# prime**1 since 64 + 32 + 4 + 1 = 101. So, we'll have to divide the
# large number exactly 7 times per prime no matter what the exponent.
# Note: 7 assumes that the encoding results in no value greater than
# 127.
def decode(input, primes, coder)
goedel_value = input.gets.to_i
max_two_expnt = (Math.log(coder.max_code) / Math.log(2)).to_i
factors = (0..max_two_expnt).map { |i| [2**i, nil] }

while goedel_value > 1
current_prime = primes.next
encoded = 0

factors[0][1] = current_prime
(1..max_two_expnt).each do |i|
factors[i][1] = factors[i - 1][1] ** 2
end

factors.reverse_each do |expnt, factor|
quotient, remainder = goedel_value.divmod(factor)
if remainder == 0
encoded += expnt
goedel_value = quotient
end
end

char = coder.decode(encoded)
putc char unless char.nil?
end
end


def usage
STDERR.puts "Usage: %s -e[ncode]|-d[ecode] [file]" % $0
exit 1
end


# process command-line args and figure out which method to call

task = nil
input = nil
ARGV.each do |arg|
case arg
when /^-+e/ : task = :encode
when /^-+d/ : task = :decode
else if input : usage
else input = open(arg)
end
end
end

input = STDIN if input.nil?
primes = Prime.new
coder = RubyQuizCoder.new

case task
when :encode : encode(input, primes, coder)
when :decode : decode(input, primes, coder)
else usage
end

Eric I.

11/19/2007 1:51:00 AM

0

One other efficiency I played with was in getting the prime values.
It turns out that using the Prime class in the 'mathn' library isn't
that fast as you get to higher primes. As a test, try figuring out
the 10,000th prime in irb.

So, it would be a lot quicker to feed the encoding and decoding
processes pre-computed primes. And it turns out you can easily
download the first 15 million primes from:

http://primes.utm.edu/lists/small...

So, here's a class that can be used in place of the 'mathn' library's
Prime class, that will get its data from the downloaded (and unzipped)
files from that source.

Eric

====

Interested in hands-on, on-site Ruby training? See http://Lea...
for information about a well-reviewed class.

========

# Generates a stream of prime numbers as they're read from a sequence
# of files with names such as "primes1.txt", "primes2.txt", and so
# forth. Such files can be downloaded from:
# http://primes.utm.edu/lists/small...


class Prime
def initialize
@current_file = 0
@io = open_next_file
@current_primes = []
@current_index = 0
end

def next
load_next_primes until value = @current_primes[@current_index]
@current_index += 1
value
end

private

def load_next_primes
while true
while line = @io.gets
if line =~ /^\s*\d+(\s+\d+)*\s*$/
@current_primes = line.split.map { |e| e.to_i }
@current_index = 0
return
end
end
@io.close
open_next_file
end
end

def open_next_file
@current_file += 1
filename = "primes%d.txt" % @current_file
begin
@io = open(filename)
rescue
raise "ran out of primes because couldn't open file \"%s\"" %
filename
end
end
end