Change the facing with a turn_left method in Ruby












3















I need to create a method turn_left who changes the facing, facing always start in :south (Im implementing a robot who moves into a board) so if i call method turn_left should change the facing to East and then to North and to West and then return to south. Im thinking in something like this:



    {
0: S
1: E
2: N
3: W
}


this is my code



# Models the Robor behavior for the game
class Robot

def initialize(attr = {})
# @position = attr[:position]
# @move = attr[:move]
@facing = :south
# @turn_left =
# @turn_right =
# @errors =
end

def position
end

def move
end

def facing
@facing
end

def turn_left

end

def turn_right
end

def errors
end
end


Thank you so much!!!










share|improve this question

























  • oh Im kinda new here I thought that I should select one if works but yea you are right! :)

    – Andrea Bazán
    Nov 13 '18 at 17:16











  • Got it! was because my whole platform is building in Rails but yea, this part is just Ruby.

    – Andrea Bazán
    Nov 13 '18 at 17:35











  • This is not a precise enough error description for us to help you. What doesn't work? How doesn't it work? What trouble do you have with your code? Do you get an error message? What is the error message? Is the result you are getting not the result you are expecting? What result do you expect and why, what is the result you are getting and how do the two differ? Is the behavior you are observing not the desired behavior? What is the desired behavior and why, what is the observed behavior, and in what way do they differ?

    – Jörg W Mittag
    Nov 13 '18 at 20:05
















3















I need to create a method turn_left who changes the facing, facing always start in :south (Im implementing a robot who moves into a board) so if i call method turn_left should change the facing to East and then to North and to West and then return to south. Im thinking in something like this:



    {
0: S
1: E
2: N
3: W
}


this is my code



# Models the Robor behavior for the game
class Robot

def initialize(attr = {})
# @position = attr[:position]
# @move = attr[:move]
@facing = :south
# @turn_left =
# @turn_right =
# @errors =
end

def position
end

def move
end

def facing
@facing
end

def turn_left

end

def turn_right
end

def errors
end
end


Thank you so much!!!










share|improve this question

























  • oh Im kinda new here I thought that I should select one if works but yea you are right! :)

    – Andrea Bazán
    Nov 13 '18 at 17:16











  • Got it! was because my whole platform is building in Rails but yea, this part is just Ruby.

    – Andrea Bazán
    Nov 13 '18 at 17:35











  • This is not a precise enough error description for us to help you. What doesn't work? How doesn't it work? What trouble do you have with your code? Do you get an error message? What is the error message? Is the result you are getting not the result you are expecting? What result do you expect and why, what is the result you are getting and how do the two differ? Is the behavior you are observing not the desired behavior? What is the desired behavior and why, what is the observed behavior, and in what way do they differ?

    – Jörg W Mittag
    Nov 13 '18 at 20:05














3












3








3








I need to create a method turn_left who changes the facing, facing always start in :south (Im implementing a robot who moves into a board) so if i call method turn_left should change the facing to East and then to North and to West and then return to south. Im thinking in something like this:



    {
0: S
1: E
2: N
3: W
}


this is my code



# Models the Robor behavior for the game
class Robot

def initialize(attr = {})
# @position = attr[:position]
# @move = attr[:move]
@facing = :south
# @turn_left =
# @turn_right =
# @errors =
end

def position
end

def move
end

def facing
@facing
end

def turn_left

end

def turn_right
end

def errors
end
end


Thank you so much!!!










share|improve this question
















I need to create a method turn_left who changes the facing, facing always start in :south (Im implementing a robot who moves into a board) so if i call method turn_left should change the facing to East and then to North and to West and then return to south. Im thinking in something like this:



    {
0: S
1: E
2: N
3: W
}


this is my code



# Models the Robor behavior for the game
class Robot

def initialize(attr = {})
# @position = attr[:position]
# @move = attr[:move]
@facing = :south
# @turn_left =
# @turn_right =
# @errors =
end

def position
end

def move
end

def facing
@facing
end

def turn_left

end

def turn_right
end

def errors
end
end


Thank you so much!!!







ruby






share|improve this question















share|improve this question













share|improve this question




share|improve this question








edited Nov 13 '18 at 17:34







Andrea Bazán

















asked Nov 13 '18 at 16:50









Andrea BazánAndrea Bazán

488




488













  • oh Im kinda new here I thought that I should select one if works but yea you are right! :)

    – Andrea Bazán
    Nov 13 '18 at 17:16











  • Got it! was because my whole platform is building in Rails but yea, this part is just Ruby.

    – Andrea Bazán
    Nov 13 '18 at 17:35











  • This is not a precise enough error description for us to help you. What doesn't work? How doesn't it work? What trouble do you have with your code? Do you get an error message? What is the error message? Is the result you are getting not the result you are expecting? What result do you expect and why, what is the result you are getting and how do the two differ? Is the behavior you are observing not the desired behavior? What is the desired behavior and why, what is the observed behavior, and in what way do they differ?

    – Jörg W Mittag
    Nov 13 '18 at 20:05



















  • oh Im kinda new here I thought that I should select one if works but yea you are right! :)

    – Andrea Bazán
    Nov 13 '18 at 17:16











  • Got it! was because my whole platform is building in Rails but yea, this part is just Ruby.

    – Andrea Bazán
    Nov 13 '18 at 17:35











  • This is not a precise enough error description for us to help you. What doesn't work? How doesn't it work? What trouble do you have with your code? Do you get an error message? What is the error message? Is the result you are getting not the result you are expecting? What result do you expect and why, what is the result you are getting and how do the two differ? Is the behavior you are observing not the desired behavior? What is the desired behavior and why, what is the observed behavior, and in what way do they differ?

    – Jörg W Mittag
    Nov 13 '18 at 20:05

















oh Im kinda new here I thought that I should select one if works but yea you are right! :)

– Andrea Bazán
Nov 13 '18 at 17:16





oh Im kinda new here I thought that I should select one if works but yea you are right! :)

– Andrea Bazán
Nov 13 '18 at 17:16













Got it! was because my whole platform is building in Rails but yea, this part is just Ruby.

– Andrea Bazán
Nov 13 '18 at 17:35





Got it! was because my whole platform is building in Rails but yea, this part is just Ruby.

– Andrea Bazán
Nov 13 '18 at 17:35













This is not a precise enough error description for us to help you. What doesn't work? How doesn't it work? What trouble do you have with your code? Do you get an error message? What is the error message? Is the result you are getting not the result you are expecting? What result do you expect and why, what is the result you are getting and how do the two differ? Is the behavior you are observing not the desired behavior? What is the desired behavior and why, what is the observed behavior, and in what way do they differ?

– Jörg W Mittag
Nov 13 '18 at 20:05





This is not a precise enough error description for us to help you. What doesn't work? How doesn't it work? What trouble do you have with your code? Do you get an error message? What is the error message? Is the result you are getting not the result you are expecting? What result do you expect and why, what is the result you are getting and how do the two differ? Is the behavior you are observing not the desired behavior? What is the desired behavior and why, what is the observed behavior, and in what way do they differ?

– Jörg W Mittag
Nov 13 '18 at 20:05












4 Answers
4






active

oldest

votes


















5














How about something like this:



class Robot
FACINGS = [:south, :east, :north, :west]

def initialize(attr = {})
@facing_index = 0 # south
end

def facing
FACINGS[@facing_index]
end

def turn_left
@facing_index += 1
@facing_index %= 4
end

def turn_right
@facing_index -= 1
@facing_index %= 4
end
end


The %= 4 (or, if you really want to generalise this further, %= FACINGS.length) performs modulo arithmetic to "wrap" the current index back into the range 0-3.



Therefore by incrementing/decrementing this number, you can toggle between the four directions.





I don't know how you intent to implement position, move and errors, but I presume that's beyond the scope of your question.






share|improve this answer
























  • Thank you so much!! :)

    – Andrea Bazán
    Nov 13 '18 at 17:09











  • Just wanted to answer it this way, and refreshed to see answers xD

    – 7urkm3n
    Nov 13 '18 at 17:11











  • Yea. Its is because I need to change position according to facing and assigns no errors if it moves succesfully.

    – Andrea Bazán
    Nov 13 '18 at 17:13



















4














You could store the directions in an array:



def initialize
@dirs = [:S, :W, :N, :E]
end


With the first entry being the facing direction:



def facing
@dirs.first
end


When the robot turns left, you rotate! the array counter clockwise:



def turn_left
@dirs.rotate! -1
end


Or clockwise when turning right: (the 1 could be omitted here)



def turn_right
@dirs.rotate! 1
end





share|improve this answer


























  • Thank you so much Stefan!!! :)

    – Andrea Bazán
    Nov 13 '18 at 17:10











  • As you know, and probably considered, an alternative is @right = [:N, :E, :S, :W].cycle; def turn_right; @facing = @right.next; end; def turn_left; 3.times { turn_right }; end; attr_reader :facing.

    – Cary Swoveland
    Nov 13 '18 at 19:22











  • @CarySwoveland if only there were "two-way" enumerators with both, next and prev.

    – Stefan
    Nov 14 '18 at 7:54











  • Yes, that would be handy.

    – Cary Swoveland
    Nov 14 '18 at 8:25



















4














left = {:n=>:w, :w=>:s, :s=>:e, :e=>:n}
right = left.invert
#=> {:w=>:n, :s=>:w, :e=>:s, :n=>:e}

pos = :s

pos = left[pos]
#=> :e
pos = right[pos]
#=> :w





share|improve this answer


























  • For this use case, I like the "old" :n=>:w syntax much more ;-)

    – Stefan
    Nov 13 '18 at 17:24











  • Your wish is my command, @Stefan. I agree. (Readers: I formerly had n: :w, etc.)

    – Cary Swoveland
    Nov 13 '18 at 17:32













  • A downside to this approach is that it's quite limited to one action ("turn left") and its inverse ("turn right"). Implementing something else, like "turn around" or turn by a different amount (if there were more than 4 directions) breaks the otherwise quite elegant design pattern.

    – Tom Lord
    Nov 13 '18 at 17:39













  • I mean, of course you can still achieve it - e.g. left[left[pos]] to turn around. It just loses its elegance.

    – Tom Lord
    Nov 13 '18 at 17:41











  • @Tom, that's true, but we could also define turn_around = { :n=>:s, :s=>:n, :e=>:w, :w=>:e }.

    – Cary Swoveland
    Nov 13 '18 at 18:56





















2














I would go with degrees instead of an enumeration. That way you can manipulate the facing by adding/subtracting n degrees from the current facing.



class Robot
attr_accessor :facing

def initialize(**attrs)
self.facing = attrs[:facing] || 180 # south
end

def rotate!(degrees)
self.facing = (self.facing + degrees) % 360
end

def rotate_left!
rotate!(-90)
end

def rotate_right!
rotate!(90)
end
end


You can then use a relatively simple method to convert degrees to cardinal (compass points):



class Robot
COMPASS_POINTS = %w[N E S W]

# ...

def compass_point
seg_size = 360 / COMPASS_POINTS.size
COMPASS_POINTS[((facing + (seg_size / 2)) % 360) / seg_size]
end
end


This one is taken from the geocoder gem.



This might seem a bit more complicated but lets you store executed commands as rotate: 90 or rotate: -90 if you want to keep track of it. It also lets you rotate the robot a full (stepless) 360 degrees if wanted.






share|improve this answer


























  • Thats so cool!! Thank you Max!

    – Andrea Bazán
    Nov 13 '18 at 18:23











  • rotate! can just be self.facing = (self.facing + degrees) % 360

    – engineersmnky
    Nov 13 '18 at 20:26






  • 1





    Thanks @engineersmnky, I knew there had to be a smarter way using modulus.

    – max
    Nov 13 '18 at 21:31











Your Answer






StackExchange.ifUsing("editor", function () {
StackExchange.using("externalEditor", function () {
StackExchange.using("snippets", function () {
StackExchange.snippets.init();
});
});
}, "code-snippets");

StackExchange.ready(function() {
var channelOptions = {
tags: "".split(" "),
id: "1"
};
initTagRenderer("".split(" "), "".split(" "), channelOptions);

StackExchange.using("externalEditor", function() {
// Have to fire editor after snippets, if snippets enabled
if (StackExchange.settings.snippets.snippetsEnabled) {
StackExchange.using("snippets", function() {
createEditor();
});
}
else {
createEditor();
}
});

function createEditor() {
StackExchange.prepareEditor({
heartbeatType: 'answer',
autoActivateHeartbeat: false,
convertImagesToLinks: true,
noModals: true,
showLowRepImageUploadWarning: true,
reputationToPostImages: 10,
bindNavPrevention: true,
postfix: "",
imageUploader: {
brandingHtml: "Powered by u003ca class="icon-imgur-white" href="https://imgur.com/"u003eu003c/au003e",
contentPolicyHtml: "User contributions licensed under u003ca href="https://creativecommons.org/licenses/by-sa/3.0/"u003ecc by-sa 3.0 with attribution requiredu003c/au003e u003ca href="https://stackoverflow.com/legal/content-policy"u003e(content policy)u003c/au003e",
allowUrls: true
},
onDemand: true,
discardSelector: ".discard-answer"
,immediatelyShowMarkdownHelp:true
});


}
});














draft saved

draft discarded


















StackExchange.ready(
function () {
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f53285855%2fchange-the-facing-with-a-turn-left-method-in-ruby%23new-answer', 'question_page');
}
);

Post as a guest















Required, but never shown

























4 Answers
4






active

oldest

votes








4 Answers
4






active

oldest

votes









active

oldest

votes






active

oldest

votes









5














How about something like this:



class Robot
FACINGS = [:south, :east, :north, :west]

def initialize(attr = {})
@facing_index = 0 # south
end

def facing
FACINGS[@facing_index]
end

def turn_left
@facing_index += 1
@facing_index %= 4
end

def turn_right
@facing_index -= 1
@facing_index %= 4
end
end


The %= 4 (or, if you really want to generalise this further, %= FACINGS.length) performs modulo arithmetic to "wrap" the current index back into the range 0-3.



Therefore by incrementing/decrementing this number, you can toggle between the four directions.





I don't know how you intent to implement position, move and errors, but I presume that's beyond the scope of your question.






share|improve this answer
























  • Thank you so much!! :)

    – Andrea Bazán
    Nov 13 '18 at 17:09











  • Just wanted to answer it this way, and refreshed to see answers xD

    – 7urkm3n
    Nov 13 '18 at 17:11











  • Yea. Its is because I need to change position according to facing and assigns no errors if it moves succesfully.

    – Andrea Bazán
    Nov 13 '18 at 17:13
















5














How about something like this:



class Robot
FACINGS = [:south, :east, :north, :west]

def initialize(attr = {})
@facing_index = 0 # south
end

def facing
FACINGS[@facing_index]
end

def turn_left
@facing_index += 1
@facing_index %= 4
end

def turn_right
@facing_index -= 1
@facing_index %= 4
end
end


The %= 4 (or, if you really want to generalise this further, %= FACINGS.length) performs modulo arithmetic to "wrap" the current index back into the range 0-3.



Therefore by incrementing/decrementing this number, you can toggle between the four directions.





I don't know how you intent to implement position, move and errors, but I presume that's beyond the scope of your question.






share|improve this answer
























  • Thank you so much!! :)

    – Andrea Bazán
    Nov 13 '18 at 17:09











  • Just wanted to answer it this way, and refreshed to see answers xD

    – 7urkm3n
    Nov 13 '18 at 17:11











  • Yea. Its is because I need to change position according to facing and assigns no errors if it moves succesfully.

    – Andrea Bazán
    Nov 13 '18 at 17:13














5












5








5







How about something like this:



class Robot
FACINGS = [:south, :east, :north, :west]

def initialize(attr = {})
@facing_index = 0 # south
end

def facing
FACINGS[@facing_index]
end

def turn_left
@facing_index += 1
@facing_index %= 4
end

def turn_right
@facing_index -= 1
@facing_index %= 4
end
end


The %= 4 (or, if you really want to generalise this further, %= FACINGS.length) performs modulo arithmetic to "wrap" the current index back into the range 0-3.



Therefore by incrementing/decrementing this number, you can toggle between the four directions.





I don't know how you intent to implement position, move and errors, but I presume that's beyond the scope of your question.






share|improve this answer













How about something like this:



class Robot
FACINGS = [:south, :east, :north, :west]

def initialize(attr = {})
@facing_index = 0 # south
end

def facing
FACINGS[@facing_index]
end

def turn_left
@facing_index += 1
@facing_index %= 4
end

def turn_right
@facing_index -= 1
@facing_index %= 4
end
end


The %= 4 (or, if you really want to generalise this further, %= FACINGS.length) performs modulo arithmetic to "wrap" the current index back into the range 0-3.



Therefore by incrementing/decrementing this number, you can toggle between the four directions.





I don't know how you intent to implement position, move and errors, but I presume that's beyond the scope of your question.







share|improve this answer












share|improve this answer



share|improve this answer










answered Nov 13 '18 at 17:03









Tom LordTom Lord

15.1k22951




15.1k22951













  • Thank you so much!! :)

    – Andrea Bazán
    Nov 13 '18 at 17:09











  • Just wanted to answer it this way, and refreshed to see answers xD

    – 7urkm3n
    Nov 13 '18 at 17:11











  • Yea. Its is because I need to change position according to facing and assigns no errors if it moves succesfully.

    – Andrea Bazán
    Nov 13 '18 at 17:13



















  • Thank you so much!! :)

    – Andrea Bazán
    Nov 13 '18 at 17:09











  • Just wanted to answer it this way, and refreshed to see answers xD

    – 7urkm3n
    Nov 13 '18 at 17:11











  • Yea. Its is because I need to change position according to facing and assigns no errors if it moves succesfully.

    – Andrea Bazán
    Nov 13 '18 at 17:13

















Thank you so much!! :)

– Andrea Bazán
Nov 13 '18 at 17:09





Thank you so much!! :)

– Andrea Bazán
Nov 13 '18 at 17:09













Just wanted to answer it this way, and refreshed to see answers xD

– 7urkm3n
Nov 13 '18 at 17:11





Just wanted to answer it this way, and refreshed to see answers xD

– 7urkm3n
Nov 13 '18 at 17:11













Yea. Its is because I need to change position according to facing and assigns no errors if it moves succesfully.

– Andrea Bazán
Nov 13 '18 at 17:13





Yea. Its is because I need to change position according to facing and assigns no errors if it moves succesfully.

– Andrea Bazán
Nov 13 '18 at 17:13













4














You could store the directions in an array:



def initialize
@dirs = [:S, :W, :N, :E]
end


With the first entry being the facing direction:



def facing
@dirs.first
end


When the robot turns left, you rotate! the array counter clockwise:



def turn_left
@dirs.rotate! -1
end


Or clockwise when turning right: (the 1 could be omitted here)



def turn_right
@dirs.rotate! 1
end





share|improve this answer


























  • Thank you so much Stefan!!! :)

    – Andrea Bazán
    Nov 13 '18 at 17:10











  • As you know, and probably considered, an alternative is @right = [:N, :E, :S, :W].cycle; def turn_right; @facing = @right.next; end; def turn_left; 3.times { turn_right }; end; attr_reader :facing.

    – Cary Swoveland
    Nov 13 '18 at 19:22











  • @CarySwoveland if only there were "two-way" enumerators with both, next and prev.

    – Stefan
    Nov 14 '18 at 7:54











  • Yes, that would be handy.

    – Cary Swoveland
    Nov 14 '18 at 8:25
















4














You could store the directions in an array:



def initialize
@dirs = [:S, :W, :N, :E]
end


With the first entry being the facing direction:



def facing
@dirs.first
end


When the robot turns left, you rotate! the array counter clockwise:



def turn_left
@dirs.rotate! -1
end


Or clockwise when turning right: (the 1 could be omitted here)



def turn_right
@dirs.rotate! 1
end





share|improve this answer


























  • Thank you so much Stefan!!! :)

    – Andrea Bazán
    Nov 13 '18 at 17:10











  • As you know, and probably considered, an alternative is @right = [:N, :E, :S, :W].cycle; def turn_right; @facing = @right.next; end; def turn_left; 3.times { turn_right }; end; attr_reader :facing.

    – Cary Swoveland
    Nov 13 '18 at 19:22











  • @CarySwoveland if only there were "two-way" enumerators with both, next and prev.

    – Stefan
    Nov 14 '18 at 7:54











  • Yes, that would be handy.

    – Cary Swoveland
    Nov 14 '18 at 8:25














4












4








4







You could store the directions in an array:



def initialize
@dirs = [:S, :W, :N, :E]
end


With the first entry being the facing direction:



def facing
@dirs.first
end


When the robot turns left, you rotate! the array counter clockwise:



def turn_left
@dirs.rotate! -1
end


Or clockwise when turning right: (the 1 could be omitted here)



def turn_right
@dirs.rotate! 1
end





share|improve this answer















You could store the directions in an array:



def initialize
@dirs = [:S, :W, :N, :E]
end


With the first entry being the facing direction:



def facing
@dirs.first
end


When the robot turns left, you rotate! the array counter clockwise:



def turn_left
@dirs.rotate! -1
end


Or clockwise when turning right: (the 1 could be omitted here)



def turn_right
@dirs.rotate! 1
end






share|improve this answer














share|improve this answer



share|improve this answer








edited Nov 13 '18 at 17:10

























answered Nov 13 '18 at 17:08









StefanStefan

75.4k894142




75.4k894142













  • Thank you so much Stefan!!! :)

    – Andrea Bazán
    Nov 13 '18 at 17:10











  • As you know, and probably considered, an alternative is @right = [:N, :E, :S, :W].cycle; def turn_right; @facing = @right.next; end; def turn_left; 3.times { turn_right }; end; attr_reader :facing.

    – Cary Swoveland
    Nov 13 '18 at 19:22











  • @CarySwoveland if only there were "two-way" enumerators with both, next and prev.

    – Stefan
    Nov 14 '18 at 7:54











  • Yes, that would be handy.

    – Cary Swoveland
    Nov 14 '18 at 8:25



















  • Thank you so much Stefan!!! :)

    – Andrea Bazán
    Nov 13 '18 at 17:10











  • As you know, and probably considered, an alternative is @right = [:N, :E, :S, :W].cycle; def turn_right; @facing = @right.next; end; def turn_left; 3.times { turn_right }; end; attr_reader :facing.

    – Cary Swoveland
    Nov 13 '18 at 19:22











  • @CarySwoveland if only there were "two-way" enumerators with both, next and prev.

    – Stefan
    Nov 14 '18 at 7:54











  • Yes, that would be handy.

    – Cary Swoveland
    Nov 14 '18 at 8:25

















Thank you so much Stefan!!! :)

– Andrea Bazán
Nov 13 '18 at 17:10





Thank you so much Stefan!!! :)

– Andrea Bazán
Nov 13 '18 at 17:10













As you know, and probably considered, an alternative is @right = [:N, :E, :S, :W].cycle; def turn_right; @facing = @right.next; end; def turn_left; 3.times { turn_right }; end; attr_reader :facing.

– Cary Swoveland
Nov 13 '18 at 19:22





As you know, and probably considered, an alternative is @right = [:N, :E, :S, :W].cycle; def turn_right; @facing = @right.next; end; def turn_left; 3.times { turn_right }; end; attr_reader :facing.

– Cary Swoveland
Nov 13 '18 at 19:22













@CarySwoveland if only there were "two-way" enumerators with both, next and prev.

– Stefan
Nov 14 '18 at 7:54





@CarySwoveland if only there were "two-way" enumerators with both, next and prev.

– Stefan
Nov 14 '18 at 7:54













Yes, that would be handy.

– Cary Swoveland
Nov 14 '18 at 8:25





Yes, that would be handy.

– Cary Swoveland
Nov 14 '18 at 8:25











4














left = {:n=>:w, :w=>:s, :s=>:e, :e=>:n}
right = left.invert
#=> {:w=>:n, :s=>:w, :e=>:s, :n=>:e}

pos = :s

pos = left[pos]
#=> :e
pos = right[pos]
#=> :w





share|improve this answer


























  • For this use case, I like the "old" :n=>:w syntax much more ;-)

    – Stefan
    Nov 13 '18 at 17:24











  • Your wish is my command, @Stefan. I agree. (Readers: I formerly had n: :w, etc.)

    – Cary Swoveland
    Nov 13 '18 at 17:32













  • A downside to this approach is that it's quite limited to one action ("turn left") and its inverse ("turn right"). Implementing something else, like "turn around" or turn by a different amount (if there were more than 4 directions) breaks the otherwise quite elegant design pattern.

    – Tom Lord
    Nov 13 '18 at 17:39













  • I mean, of course you can still achieve it - e.g. left[left[pos]] to turn around. It just loses its elegance.

    – Tom Lord
    Nov 13 '18 at 17:41











  • @Tom, that's true, but we could also define turn_around = { :n=>:s, :s=>:n, :e=>:w, :w=>:e }.

    – Cary Swoveland
    Nov 13 '18 at 18:56


















4














left = {:n=>:w, :w=>:s, :s=>:e, :e=>:n}
right = left.invert
#=> {:w=>:n, :s=>:w, :e=>:s, :n=>:e}

pos = :s

pos = left[pos]
#=> :e
pos = right[pos]
#=> :w





share|improve this answer


























  • For this use case, I like the "old" :n=>:w syntax much more ;-)

    – Stefan
    Nov 13 '18 at 17:24











  • Your wish is my command, @Stefan. I agree. (Readers: I formerly had n: :w, etc.)

    – Cary Swoveland
    Nov 13 '18 at 17:32













  • A downside to this approach is that it's quite limited to one action ("turn left") and its inverse ("turn right"). Implementing something else, like "turn around" or turn by a different amount (if there were more than 4 directions) breaks the otherwise quite elegant design pattern.

    – Tom Lord
    Nov 13 '18 at 17:39













  • I mean, of course you can still achieve it - e.g. left[left[pos]] to turn around. It just loses its elegance.

    – Tom Lord
    Nov 13 '18 at 17:41











  • @Tom, that's true, but we could also define turn_around = { :n=>:s, :s=>:n, :e=>:w, :w=>:e }.

    – Cary Swoveland
    Nov 13 '18 at 18:56
















4












4








4







left = {:n=>:w, :w=>:s, :s=>:e, :e=>:n}
right = left.invert
#=> {:w=>:n, :s=>:w, :e=>:s, :n=>:e}

pos = :s

pos = left[pos]
#=> :e
pos = right[pos]
#=> :w





share|improve this answer















left = {:n=>:w, :w=>:s, :s=>:e, :e=>:n}
right = left.invert
#=> {:w=>:n, :s=>:w, :e=>:s, :n=>:e}

pos = :s

pos = left[pos]
#=> :e
pos = right[pos]
#=> :w






share|improve this answer














share|improve this answer



share|improve this answer








edited Nov 13 '18 at 17:31

























answered Nov 13 '18 at 17:13









Cary SwovelandCary Swoveland

68.3k53965




68.3k53965













  • For this use case, I like the "old" :n=>:w syntax much more ;-)

    – Stefan
    Nov 13 '18 at 17:24











  • Your wish is my command, @Stefan. I agree. (Readers: I formerly had n: :w, etc.)

    – Cary Swoveland
    Nov 13 '18 at 17:32













  • A downside to this approach is that it's quite limited to one action ("turn left") and its inverse ("turn right"). Implementing something else, like "turn around" or turn by a different amount (if there were more than 4 directions) breaks the otherwise quite elegant design pattern.

    – Tom Lord
    Nov 13 '18 at 17:39













  • I mean, of course you can still achieve it - e.g. left[left[pos]] to turn around. It just loses its elegance.

    – Tom Lord
    Nov 13 '18 at 17:41











  • @Tom, that's true, but we could also define turn_around = { :n=>:s, :s=>:n, :e=>:w, :w=>:e }.

    – Cary Swoveland
    Nov 13 '18 at 18:56





















  • For this use case, I like the "old" :n=>:w syntax much more ;-)

    – Stefan
    Nov 13 '18 at 17:24











  • Your wish is my command, @Stefan. I agree. (Readers: I formerly had n: :w, etc.)

    – Cary Swoveland
    Nov 13 '18 at 17:32













  • A downside to this approach is that it's quite limited to one action ("turn left") and its inverse ("turn right"). Implementing something else, like "turn around" or turn by a different amount (if there were more than 4 directions) breaks the otherwise quite elegant design pattern.

    – Tom Lord
    Nov 13 '18 at 17:39













  • I mean, of course you can still achieve it - e.g. left[left[pos]] to turn around. It just loses its elegance.

    – Tom Lord
    Nov 13 '18 at 17:41











  • @Tom, that's true, but we could also define turn_around = { :n=>:s, :s=>:n, :e=>:w, :w=>:e }.

    – Cary Swoveland
    Nov 13 '18 at 18:56



















For this use case, I like the "old" :n=>:w syntax much more ;-)

– Stefan
Nov 13 '18 at 17:24





For this use case, I like the "old" :n=>:w syntax much more ;-)

– Stefan
Nov 13 '18 at 17:24













Your wish is my command, @Stefan. I agree. (Readers: I formerly had n: :w, etc.)

– Cary Swoveland
Nov 13 '18 at 17:32







Your wish is my command, @Stefan. I agree. (Readers: I formerly had n: :w, etc.)

– Cary Swoveland
Nov 13 '18 at 17:32















A downside to this approach is that it's quite limited to one action ("turn left") and its inverse ("turn right"). Implementing something else, like "turn around" or turn by a different amount (if there were more than 4 directions) breaks the otherwise quite elegant design pattern.

– Tom Lord
Nov 13 '18 at 17:39







A downside to this approach is that it's quite limited to one action ("turn left") and its inverse ("turn right"). Implementing something else, like "turn around" or turn by a different amount (if there were more than 4 directions) breaks the otherwise quite elegant design pattern.

– Tom Lord
Nov 13 '18 at 17:39















I mean, of course you can still achieve it - e.g. left[left[pos]] to turn around. It just loses its elegance.

– Tom Lord
Nov 13 '18 at 17:41





I mean, of course you can still achieve it - e.g. left[left[pos]] to turn around. It just loses its elegance.

– Tom Lord
Nov 13 '18 at 17:41













@Tom, that's true, but we could also define turn_around = { :n=>:s, :s=>:n, :e=>:w, :w=>:e }.

– Cary Swoveland
Nov 13 '18 at 18:56







@Tom, that's true, but we could also define turn_around = { :n=>:s, :s=>:n, :e=>:w, :w=>:e }.

– Cary Swoveland
Nov 13 '18 at 18:56













2














I would go with degrees instead of an enumeration. That way you can manipulate the facing by adding/subtracting n degrees from the current facing.



class Robot
attr_accessor :facing

def initialize(**attrs)
self.facing = attrs[:facing] || 180 # south
end

def rotate!(degrees)
self.facing = (self.facing + degrees) % 360
end

def rotate_left!
rotate!(-90)
end

def rotate_right!
rotate!(90)
end
end


You can then use a relatively simple method to convert degrees to cardinal (compass points):



class Robot
COMPASS_POINTS = %w[N E S W]

# ...

def compass_point
seg_size = 360 / COMPASS_POINTS.size
COMPASS_POINTS[((facing + (seg_size / 2)) % 360) / seg_size]
end
end


This one is taken from the geocoder gem.



This might seem a bit more complicated but lets you store executed commands as rotate: 90 or rotate: -90 if you want to keep track of it. It also lets you rotate the robot a full (stepless) 360 degrees if wanted.






share|improve this answer


























  • Thats so cool!! Thank you Max!

    – Andrea Bazán
    Nov 13 '18 at 18:23











  • rotate! can just be self.facing = (self.facing + degrees) % 360

    – engineersmnky
    Nov 13 '18 at 20:26






  • 1





    Thanks @engineersmnky, I knew there had to be a smarter way using modulus.

    – max
    Nov 13 '18 at 21:31
















2














I would go with degrees instead of an enumeration. That way you can manipulate the facing by adding/subtracting n degrees from the current facing.



class Robot
attr_accessor :facing

def initialize(**attrs)
self.facing = attrs[:facing] || 180 # south
end

def rotate!(degrees)
self.facing = (self.facing + degrees) % 360
end

def rotate_left!
rotate!(-90)
end

def rotate_right!
rotate!(90)
end
end


You can then use a relatively simple method to convert degrees to cardinal (compass points):



class Robot
COMPASS_POINTS = %w[N E S W]

# ...

def compass_point
seg_size = 360 / COMPASS_POINTS.size
COMPASS_POINTS[((facing + (seg_size / 2)) % 360) / seg_size]
end
end


This one is taken from the geocoder gem.



This might seem a bit more complicated but lets you store executed commands as rotate: 90 or rotate: -90 if you want to keep track of it. It also lets you rotate the robot a full (stepless) 360 degrees if wanted.






share|improve this answer


























  • Thats so cool!! Thank you Max!

    – Andrea Bazán
    Nov 13 '18 at 18:23











  • rotate! can just be self.facing = (self.facing + degrees) % 360

    – engineersmnky
    Nov 13 '18 at 20:26






  • 1





    Thanks @engineersmnky, I knew there had to be a smarter way using modulus.

    – max
    Nov 13 '18 at 21:31














2












2








2







I would go with degrees instead of an enumeration. That way you can manipulate the facing by adding/subtracting n degrees from the current facing.



class Robot
attr_accessor :facing

def initialize(**attrs)
self.facing = attrs[:facing] || 180 # south
end

def rotate!(degrees)
self.facing = (self.facing + degrees) % 360
end

def rotate_left!
rotate!(-90)
end

def rotate_right!
rotate!(90)
end
end


You can then use a relatively simple method to convert degrees to cardinal (compass points):



class Robot
COMPASS_POINTS = %w[N E S W]

# ...

def compass_point
seg_size = 360 / COMPASS_POINTS.size
COMPASS_POINTS[((facing + (seg_size / 2)) % 360) / seg_size]
end
end


This one is taken from the geocoder gem.



This might seem a bit more complicated but lets you store executed commands as rotate: 90 or rotate: -90 if you want to keep track of it. It also lets you rotate the robot a full (stepless) 360 degrees if wanted.






share|improve this answer















I would go with degrees instead of an enumeration. That way you can manipulate the facing by adding/subtracting n degrees from the current facing.



class Robot
attr_accessor :facing

def initialize(**attrs)
self.facing = attrs[:facing] || 180 # south
end

def rotate!(degrees)
self.facing = (self.facing + degrees) % 360
end

def rotate_left!
rotate!(-90)
end

def rotate_right!
rotate!(90)
end
end


You can then use a relatively simple method to convert degrees to cardinal (compass points):



class Robot
COMPASS_POINTS = %w[N E S W]

# ...

def compass_point
seg_size = 360 / COMPASS_POINTS.size
COMPASS_POINTS[((facing + (seg_size / 2)) % 360) / seg_size]
end
end


This one is taken from the geocoder gem.



This might seem a bit more complicated but lets you store executed commands as rotate: 90 or rotate: -90 if you want to keep track of it. It also lets you rotate the robot a full (stepless) 360 degrees if wanted.







share|improve this answer














share|improve this answer



share|improve this answer








edited Nov 13 '18 at 21:31

























answered Nov 13 '18 at 17:59









maxmax

45.3k859103




45.3k859103













  • Thats so cool!! Thank you Max!

    – Andrea Bazán
    Nov 13 '18 at 18:23











  • rotate! can just be self.facing = (self.facing + degrees) % 360

    – engineersmnky
    Nov 13 '18 at 20:26






  • 1





    Thanks @engineersmnky, I knew there had to be a smarter way using modulus.

    – max
    Nov 13 '18 at 21:31



















  • Thats so cool!! Thank you Max!

    – Andrea Bazán
    Nov 13 '18 at 18:23











  • rotate! can just be self.facing = (self.facing + degrees) % 360

    – engineersmnky
    Nov 13 '18 at 20:26






  • 1





    Thanks @engineersmnky, I knew there had to be a smarter way using modulus.

    – max
    Nov 13 '18 at 21:31

















Thats so cool!! Thank you Max!

– Andrea Bazán
Nov 13 '18 at 18:23





Thats so cool!! Thank you Max!

– Andrea Bazán
Nov 13 '18 at 18:23













rotate! can just be self.facing = (self.facing + degrees) % 360

– engineersmnky
Nov 13 '18 at 20:26





rotate! can just be self.facing = (self.facing + degrees) % 360

– engineersmnky
Nov 13 '18 at 20:26




1




1





Thanks @engineersmnky, I knew there had to be a smarter way using modulus.

– max
Nov 13 '18 at 21:31





Thanks @engineersmnky, I knew there had to be a smarter way using modulus.

– max
Nov 13 '18 at 21:31


















draft saved

draft discarded




















































Thanks for contributing an answer to Stack Overflow!


  • Please be sure to answer the question. Provide details and share your research!

But avoid



  • Asking for help, clarification, or responding to other answers.

  • Making statements based on opinion; back them up with references or personal experience.


To learn more, see our tips on writing great answers.




draft saved


draft discarded














StackExchange.ready(
function () {
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f53285855%2fchange-the-facing-with-a-turn-left-method-in-ruby%23new-answer', 'question_page');
}
);

Post as a guest















Required, but never shown





















































Required, but never shown














Required, but never shown












Required, but never shown







Required, but never shown

































Required, but never shown














Required, but never shown












Required, but never shown







Required, but never shown







Popular posts from this blog

Bressuire

Vorschmack

Quarantine