Skip to content

Commit

Permalink
refactored scatter_swap a bit
Browse files Browse the repository at this point in the history
  • Loading branch information
namick committed Feb 12, 2012
1 parent 7365d3f commit 3e1ac9d
Show file tree
Hide file tree
Showing 5 changed files with 79 additions and 45 deletions.
3 changes: 3 additions & 0 deletions .rspec
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
--color
--fail-fast
--format documentation
3 changes: 2 additions & 1 deletion Guardfile
Original file line number Diff line number Diff line change
Expand Up @@ -11,9 +11,10 @@ guard 'spork', :cucumber_env => { 'RAILS_ENV' => 'test' }, :rspec_env => { 'RAIL
watch('spec/spec_helper.rb') { :rspec }
end

guard 'rspec', :cli => "--color --format nested --drb", :version => 2 do
guard 'rspec', :cli => "--color --format nested --drb --fail-fast", :version => 2 do
watch(%r{^spec/.+_spec\.rb$})
watch(%r{^lib/(.+)\.rb$}) { |m| "spec/lib/#{m[1]}_spec.rb" }
watch(%r{^lib/(.+)/(.+)\.rb$}) { |m| "spec/lib/#{m[2]}_spec.rb" }
watch('spec/spec_helper.rb') { "spec" }

# Rails example
Expand Down
87 changes: 54 additions & 33 deletions lib/obfuscate_id/scatter_swap.rb
Original file line number Diff line number Diff line change
Expand Up @@ -47,69 +47,90 @@ class ScatterSwap
# can reverse it.

# obfuscates an integer up to 10 digits in length
def self.hash(original_integer, spin = 0)
@spin = spin
original = arrayify(original_integer)
hashed = scatter(swap(original))
hashed.join
def self.hash(plain_integer, spin = 0)
new(plain_integer, spin).hash
end

def self.reverse_hash(hashed_integer, spin = 0)
new(hashed_integer, spin).reverse_hash
end

def initialize(original_integer, spin = 0)
@original_integer = original_integer
@spin = spin
hashed = arrayify(hashed_integer)
original = unswap(unscatter(hashed))
original.join
zero_pad = original_integer.to_s.rjust(10, '0')
@working_array = zero_pad.split("").collect {|d| d.to_i}
end

def self.swap(array)
array.collect.with_index do |digit, index|
swapper_map(index)[digit]
end
attr_accessor :working_array

def hash
swap
scatter
completed_string
end

def self.unswap(array)
array.collect.with_index do |digit, index|
swapper_map(index).rindex(digit)
end
def reverse_hash
unscatter
unswap
completed_string
end

def completed_string
@working_array.join
end

def completed_integer
completed_string.to_i
end

# We want a unique map for each place in the original number
def self.swapper_map(index)
def swapper_map(index)
array = (0..9).to_a
10.times.collect.with_index do |i|
array.rotate!(index + i ^ spin).pop
end
end

def swap
@working_array = @working_array.collect.with_index do |digit, index|
swapper_map(index)[digit]
end
end


def unswap
@working_array = @working_array.collect.with_index do |digit, index|
swapper_map(index).rindex(digit)
end
end

# rearrange the order of each digit in a reversable way by using the
# sum of the digits (which doesn't change regardless of order)
# as a key to record how they were scattered
def self.scatter(array)
sum_of_digits = array.inject(:+).to_i
10.times.collect do
array.rotate!(spin ^ sum_of_digits).pop
def scatter
sum_of_digits = @working_array.inject(:+).to_i
@working_array = 10.times.collect do
@working_array.rotate!(spin ^ sum_of_digits).pop
end
end

def self.unscatter(array)
sum_of_digits = array.inject(:+).to_i
[].tap do |original|
def unscatter
scattered_array = @working_array
sum_of_digits = scattered_array.inject(:+).to_i
@working_array = []
@working_array.tap do |unscatter|
10.times do
original.push(array.pop).rotate!((sum_of_digits ^ spin)* -1)
unscatter.push scattered_array.pop
unscatter.rotate! (sum_of_digits ^ spin) * -1
end
end
end

# zero pad if less than 10 digits
# and split into an array of single digit integers
def self.arrayify(integer)
integer.to_s.rjust(10, '0').split("").collect {|d| d.to_i}
end

def self.spin

def spin
@spin || 0
end



end
File renamed without changes.
31 changes: 20 additions & 11 deletions spec/scatter_swap_spec.rb → spec/lib/scatter_swap_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -24,8 +24,9 @@
describe "#swapper_map" do
before do
@map_set = []
s = ScatterSwap.new(1)
10.times do |digit|
@map_set.push ScatterSwap.swapper_map(digit)
@map_set.push s.swapper_map(digit)
end
end

Expand All @@ -45,31 +46,39 @@
describe "#scatter" do
it "should return a number different from original" do
100.times do |integer|
array = ScatterSwap.arrayify(integer)
ScatterSwap.scatter(array).should_not == integer
s = ScatterSwap.new(integer)
original_array = s.working_array
s.scatter
s.working_array.should_not == original_array
end
end
it "should be reversable" do
100.times do |integer|
original = ScatterSwap.arrayify(integer)
scattered = ScatterSwap.scatter(original.clone)
ScatterSwap.unscatter(scattered).should == original
s = ScatterSwap.new(integer)
original_array = s.working_array.clone
s.scatter
s.unscatter
s.working_array.should == original_array
end
end
end

describe "#swap" do
it "should be different from original" do
100.times do |integer|
original = ScatterSwap.arrayify(integer)
ScatterSwap.swap(original.clone).should_not == original
s = ScatterSwap.new(integer)
original_array = s.working_array.clone
s.swap
s.working_array.should_not == original_array
end
end
it "should be reversable" do
100.times do |integer|
original = ScatterSwap.arrayify(integer)
swapped = ScatterSwap.swap(original.clone)
ScatterSwap.unswap(swapped.clone).should == original
s = ScatterSwap.new(integer)
original_array = s.working_array.clone
s.swap
s.unswap
s.working_array.should == original_array
end
end
end

0 comments on commit 3e1ac9d

Please sign in to comment.