Velocity Reviews - Computer Hardware Reviews

Velocity Reviews > Newsgroups > Programming > Ruby > The opposite of .succ! (though it still may)

Reply
Thread Tools

The opposite of .succ! (though it still may)

 
 
illocutionist
Guest
Posts: n/a
 
      03-05-2004
# An opposite to .succ! Or, a predecessor method for String.

# This little thing is for my own use, and entertainment.
# There are those that might recoil from by beginners drivel, but I
# need a little help...

# I keep getting 'out of range' error no matter what I try
# when "a".pred!

class String

def pred!
begin
# get the ascii value of the last element in string and decrement it...
self[self.size - 1] = (self[self.size - 1] - 1)

if self[self.size - 1] == 96 # 'a' is the last char we want
self.chop! # when 'a'.pred! .chop char
self[self.size - 1] = 122 # set new last element to 'z'
end
return self
end while self.size > 0 # hmmmm...
end
end
 
Reply With Quote
 
 
 
 
Bill Kelly
Guest
Posts: n/a
 
      03-05-2004
Hi,

> # An opposite to .succ! Or, a predecessor method for String.
>
> # This little thing is for my own use, and entertainment.
> # There are those that might recoil from by beginners drivel, but I
> # need a little help...
>
> # I keep getting 'out of range' error no matter what I try
> # when "a".pred!
>
> class String
>
> def pred!
> begin
> # get the ascii value of the last element in string and decrement it...
> self[self.size - 1] = (self[self.size - 1] - 1)
>
> if self[self.size - 1] == 96 # 'a' is the last char we want
> self.chop! # when 'a'.pred! .chop char
> self[self.size - 1] = 122 # set new last element to 'z'
> end
> return self
> end while self.size > 0 # hmmmm...
> end
> end


IRB can be a big help in trying out bits of code interactively...

irb --simple-prompt

>> x = "a"

=> "a"

# let's try the first line there...
# self[self.size - 1] = (self[self.size - 1] - 1)
>> x[x.size - 1] = x[x.size - 1] - 1

=> 96
>> x

=> "`"
# so far so good...

# ...Incidentally, that line can be written shorter,
# using a negative index to index relative to the end
# of the container, and -= method to decrement...
>> x = "a"

=> "a"
>> x[-1] -= 1 # same as: x[x.size - 1] = x[x.size - 1] - 1

=> 96
>> x

=> "`"
# same result...

# OK.. let's try the next line,
# if self[self.size - 1] == 96
>> x[-1] == 96 # same thing, using simpler index

=> true

# OK continuing on...
>> x.chop!

=> ""
>> x

=> ""
# well we've chopped our lone character down to nothing...

# we're now about to try this line:
# self[self.size - 1] = 122

# Let's see what self.size - 1 would be...
>> x.size - 1

=> -1

# Hmm, so . . .
>> x[x.size - 1] = 122

IndexError: index -1 out of string
from (irb):13:in `[]='
from (irb):13



So I guess the routine needs some logic to bail out on
a lone 'a' ... Or bail out when the chop! reduces the
string to zero length? (Not sure what the desired
outcome is ..


Hope this helps,

Regards,

Bill




 
Reply With Quote
 
 
 
 
Mark Hubbart
Guest
Posts: n/a
 
      03-05-2004
Hi,

On Mar 5, 2004, at 1:09 AM, illocutionist wrote:

> # An opposite to .succ! Or, a predecessor method for String.
>
> # This little thing is for my own use, and entertainment
> # There are those that might recoil from by beginners drivel, but I
> # need a little help...
>
> # I keep getting 'out of range' error no matter what I try
> # when "a".pred!
>
> class String
>
> def pred!
> begin
> # get the ascii value of the last element in string and decrement it...
> self[self.size - 1] = (self[self.size - 1] - 1)
>
> if self[self.size - 1] == 96 # 'a' is the last char we
> want
> self.chop! # when 'a'.pred! .chop
> char
> self[self.size - 1] = 122 # set new last element
> to 'z'
> end
> return self
> end while self.size > 0 # hmmmm...
> end
> end


First of all: You're doing too much work! there are a couple things
you an do that will make the code smaller, and even easier to read.

Take this line:
self[self.size - 1] = (self[self.size - 1] - 1)

first: when using array notation, there is an easier way to get the
last element. You can leave off the "self.size" and just have the -1
part
self[-1] = (self[-1] - 1)

next, since array notation can be used for both assignment and
retrieval, you can use "-="
self[-1] -= 1 # this decrements the last character

However, I think that there is a logic error in your code...
>> 'cba'.pred!

=> "cz"
>> 'cba'.pred!.succ!

=> "da"

shouldn't "'cba'.pred!.succ!" return 'cba'?

looking at your code, I see that you are decrementing the last
character, then chopping it if it is under-valued. What you really want
to do is decrement the character to it's left, and set the last
character to 'z'.

if self[-1] > 97 # it's bigger than a
self[-1] -= 1
else # it is a. look to the left.
# decrement char to left, set self[-1] to z
# unless there is no char to the left, in which case, return ''
end

There's more, but I'll leave the rest as an exercise

--Mark



 
Reply With Quote
 
Mauricio Fernández
Guest
Posts: n/a
 
      03-06-2004
On Fri, Mar 05, 2004 at 06:09:43PM +0900, illocutionist wrote:
> # An opposite to .succ! Or, a predecessor method for String.
>
> # This little thing is for my own use, and entertainment.
> # There are those that might recoil from by beginners drivel, but I
> # need a little help...
>
> # I keep getting 'out of range' error no matter what I try
> # when "a".pred!
>
> class String
>
> def pred!
> begin
> # get the ascii value of the last element in string and decrement it...
> self[self.size - 1] = (self[self.size - 1] - 1)
>
> if self[self.size - 1] == 96 # 'a' is the last char we want
> self.chop! # when 'a'.pred! .chop char
> self[self.size - 1] = 122 # set new last element to 'z'
> end
> return self
> end while self.size > 0 # hmmmm...
> end
> end


>> "abcd".my_pred_alpha

=> "abcc"
>> "abcd".my_succ_alpha

=> "abce"
>> "z".my_succ_alpha

=> "00"
>> "00".my_pred_alpha

=> "z"

batsman@tux-chan:/tmp$ ruby /tmp/yy.rb
Loaded suite /tmp/yy
Started
.....
Finished in 1.525721 seconds.

5 tests, 20011 assertions, 0 failures, 0 errors


class String
ALPHA = [('0'..'9'), ('A'..'Z'), ('a'..'z')].
inject([]){|a,b| a + b.to_a}.map{|x| x[0]}

def my_succ_alpha
vals = self.unpack("C*")
carry = (vals.size-1).downto(0) do |idx|
if (i = ALPHA.index(vals[idx])) < ALPHA.size - 1
vals[idx] = ALPHA[i+1]
break false
else
vals[idx] = ALPHA[0]
end
end
vals.unshift(ALPHA[0]) if carry
vals.pack("C*")
end

def my_pred_alpha # breaks for "0"
vals = self.unpack("C*")
carry = (vals.size-1).downto(0) do |idx|
if (i = ALPHA.index(vals[idx])) > 0
vals[idx] = ALPHA[i-1]
break false
else
vals[idx] = ALPHA[-1]
end
end
vals.shift if carry
vals.pack("C*")
end

def my_succ # just operating on byte values
vals = self.unpack("C*")
carry = (vals.size-1).downto(0) do |idx|
if vals[idx] < 255
vals[idx] += 1
break false
else
vals[idx] = 0
end
end
vals.unshift(0) if carry
vals.pack("C*")
end

def my_pred # 'reverse' of my_succ
vals = self.unpack("C*")
carry = (vals.size-1).downto(0) do |idx|
if vals[idx] > 0
vals[idx] -= 1
break false
else
vals[idx] = 255
end
end
vals.shift if carry
vals.pack("C*")
end
end

require 'test/unit'

class TC_my_succ < Test::Unit::TestCase
def arr_succ(a)
a.pack("C*").my_succ.unpack("C*")
end

def arr_pred(a)
a.pack("C*").my_pred.unpack("C*")
end

def test_rand
5000.times do
txt = (0..rand(20)).map{rand(255)}.pack("C*")
assert_equal(txt, txt.my_succ.my_pred)
assert_equal(txt, txt.my_pred.my_succ)
end
end

def test_rand_alpha
5000.times do
txt = (0..rand(20)).inject("") do |a,b|
a << String::ALPHA[rand(String::ALPHA.size)]
end
next if txt == "0" # my_pred_alpha is undefined
assert_equal(txt, txt.my_succ_alpha.my_pred_alpha)
assert_equal(txt, txt.my_pred_alpha.my_succ_alpha)
end
end

def test_my_pred_alpha
assert_equal("aa", "ab".my_pred_alpha)
assert_equal("aZ", "aa".my_pred_alpha)
assert_equal("z", "00".my_pred_alpha)
assert_equal("0", "1".my_pred_alpha)
assert_equal("00", "01".my_pred_alpha)
assert_equal("9", "A".my_pred_alpha)
end

def test_my_succ
assert_equal("ab", "aa".my_succ)
assert_equal("a:", "a9".my_succ)
assert_equal([0, 0], arr_succ([255]))
assert_equal([?b, 0], arr_succ([?a, 255]))
end

def test_my_pred
assert_equal("aa", "ab".my_pred)
assert_equal("a9", "a:".my_pred)
assert_equal([0, 255], arr_pred([1,0]))
assert_equal([255], arr_pred([0,0]))
assert_equal([?a, 255], arr_pred([?b, 0]))
end
end


--
Running Debian GNU/Linux Sid (unstable)
batsman dot geo at yahoo dot com

*** PUBLIC flooding detected from erikyyy
<lewnie> THAT's an erik, pholx....
-- Seen on #LinuxGER


 
Reply With Quote
 
 
 
Reply

Thread Tools

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is On
HTML code is Off
Trackbacks are On
Pingbacks are On
Refbacks are Off


Similar Threads
Thread Thread Starter Forum Replies Last Post
is there an opposite of server.mappath? darrel ASP .Net 5 05-09-2005 02:52 PM
ne1 have a script to prevent opposite mouse, preventing image theft? with message? CB HTML 9 12-04-2004 11:05 AM
Opposite of ResultSetMetaData.getColumnName() ?? Is not: putColumnName() Arnold Peters Java 0 10-16-2004 05:10 PM
Opposite of yield? achrist@easystreet.com Python 22 09-17-2003 11:09 AM
opposite of dict.items() Tertius Python 6 08-29-2003 05:34 PM



Advertisments