How to remove opposite values ​​from an array?

I have a problem when I try to create an array of directions in which each direction is not redundant.

plan = ["NORTH", "SOUTH", "SOUTH", "EAST", "WEST", "NORTH", "WEST"] 

As you can see, most of the values ​​in this plan are redundant, and you can just tell the person to go "WEST" .

 plan = ["NORTH", "WEST", "SOUTH", "EAST"] 

I also want the above plan to return an empty array.

+7
arrays ruby
source share
5 answers

Given an array of directions:

 plan = %w[NORTH SOUTH SOUTH EAST WEST NORTH WEST] #=> ["NORTH", "SOUTH", "SOUTH", "EAST", "WEST", "NORTH", "WEST"] 

I would translate the directions to the x and y coordinates:

 x, y = 0, 0 plan.each do |direction| case direction when 'NORTH' then y += 1 when 'EAST' then x += 1 when 'SOUTH' then y -= 1 when 'WEST' then x -= 1 end end 

'NORTH' increases y , 'SOUTH' decreases y , the same goes for 'EAST' / 'WEST' and x .

In an array example, this gives:

 x #=> -1 y #=> 0 

They should be transferred back to the array of directions:

 [ *Array.new(y.abs) { y.positive? ? 'NORTH' : 'SOUTH' }, *Array.new(x.abs) { x.positive? ? 'EAST' : 'WEST' } ] #=> ["WEST"] 

Although this is not the shortest code, IMO is relatively easy to understand.

+5
source share
 OPPOSITES = { 'NORTH' => 'SOUTH', 'WEST' => 'EAST', 'EAST' => 'WEST', 'SOUTH' => 'NORTH', } frequencies = plan.group_by(&:itself).map do |direction, occurrences| [direction, occurrences.size] end.to_h OPPOSITES.flat_map do |direction, opposite_direction| uncounteracted_occurances = frequencies[direction] - frequencies[opposite_direction] [direction] * [uncounteracted_occurances, 0].max end 
+4
source share
 def simplify(plan) h = { "SOUTH"=>"NORTH", "NORTH"=>"SOUTH", "EAST"=>"WEST", "WEST"=>"EAST" } plan.each_with_object([]) { |direction, arr| (idx = arr.index(h[direction])) ? arr.delete_at(idx) : arr << direction } end simplify ["NORTH", "SOUTH", "SOUTH", "EAST", "WEST", "NORTH", "WEST"] #=> ["WEST"] simplify ["NORTH", "SOUTH", "EAST", "WEST", "NORTH", "WEST", "WEST"] #=> ["NORTH", "WEST", "WEST"] simplify ["NORTH", "EAST", "WEST", "NORTH", "WEST"] #=> ["NORTH", "NORTH", "WEST"] 
+2
source share

This is an approach that should be simple. Like my almost deleted answer, it considers directions on a 2D numerical plan, but without unnecessary complexity (pun intended). As a result, this conceptually looks like a great answer already posted by @Stefan.

 def kanye plan r = plan.count("EAST") - plan.count("WEST") i = plan.count("NORTH") - plan.count("SOUTH") res = [] r.positive? ? r.times { res << "EAST" } : (-r).times { res << "WEST" } i.positive? ? i.times { res << "NORTH" } : (-i).times { res << "SOUTH" } res end 

Examples:

 plan = ["NORTH", "SOUTH", "SOUTH", "EAST", "WEST", "NORTH", "WEST"] kanye plan #=> ["WEST"] plan = ["NORTH", "WEST", "SOUTH", "EAST"] kanye plan #=> [] plan = ["NORTH"] kanye plan #=> ["NORTH"] plan = [] kanye plan #=> [] 
0
source share

We can use the Arganda-Gauss plane to represent geographic coordinates, where we tell the real part to the north-south movements, and the imaginary part - in the east-west direction. Thus, it will be sufficient to perform a simple sum of complex numbers.

 plan=["NORTH", "SOUTH", "SOUTH", "EAST", "WEST", "NORTH", "WEST"] dict = {"NORTH"=>1, "SOUTH"=>-1, "EAST"=>(0+1i), "WEST"=>(0-1i)} # We substitute for each direction a complex number dict.each{|coord,number| plan.map!{|item| item==coord ? number : item}} # We run a simple sum direction = plan.reduce(&:+) # (0-1i) puts dict.key(direction) #=> WEST re=direction.real im=direction.imag if re!=0 and im!=0 puts "Direction: #{re.abs} #{dict.key(re/re.abs)} #{im.abs} #{dict.key((im/im.abs) *(1i))}" elsif re!=0 and im==0 puts "Direction: #{re.abs} #{dict.key(re/re.abs)}" elsif re==0 and im!=0 puts "Direction: #{im.abs} #{dict.key((im/im.abs) *(1i))}" else puts "I did not move" end #=> Direction: 1 WEST 
0
source share

All Articles