Mow a Rectangular Lawn

17

2

A lawn is defined as a rectangular field with of one character surrounded by two layers of visible whitespace. This means two lines above and twos lines below, and a two space padding on the left (the right has visible whitespace, so you do not need to include it).

  
  
  ||||| 
  ||||| 
  ||||| 
 
  

A mowed lawn is a similar structure, except that the main character is a shortened version of the first character.

  
  
  ..... 
  ..... 
  ..... 
 
  

A mower is two different characters, different than the two lawn characters. Here is an example, with = as the back of the mower and o as the front:

=o

A mower will move around the lawn vertically, and can also rotate on its front. The above mower may look like any of the below during some point in the animation:

=o 
  
o= 
  
o
=
  
=
o

The mower can start on any set of the below positions on the below lawn. Mowers with o would drive around the lawn clockwise. Mowers with 0 would drive around the lawn counterclockwise.

  =   =
  0   o
=o|||||0=
  ||||| 
=0|||||o=
  o   0
  =   =

The animation starts at second 0. Each second, the mower moves forward one space, and cut the grass on its front. When the mower vacates a spot, it appears cut. When the mower front reaches the last uncut item on a line (and there is still uncut grass), the mower back rotates once so as to continue the current mow (staying in clockwise/counterclockwise based on original position) When the mower is finished, it continues straight (mowing already cut grass) until it is completely off the lawn.

With a mower starting in the left top, this shows the basic progression for a 5x3 lawn:

Second 0  Second 1  Second 2  Second 3  Second 4  Second 5  Second 6  Second 7  Second 8  Second 9  Second 10 Second 11 Second 12 Second 13 Second 14 Second 15 Second 16 Second 17 Second 18 Second 19 Second 20 Second 21 Second 22

                                                                  =
=o|||||    =o||||     =o|||     .=o||     ..=o|     ...=o     ....o     ....=     .....     .....     .....     .....     .....     .....     .....     .....     .....     .....     .....     .....     .....     .....     .....
  |||||     |||||     |||||     |||||     |||||     |||||     |||||     ||||o     ||||=     ||||.     ||||.     ||||.     ||||.     ||||.     ||||.     o|||.    =o|||.     =o||.     .=o|.     ..=o.     ...=o     ....=o    .....=o
  |||||     |||||     |||||     |||||     |||||     |||||     |||||     |||||     ||||o     ||||o=    |||o=     ||o=.     |o=..     o=...     o....     =....     .....     .....     .....     .....     .....     .....     .....
                                                                                                                                              =
  

Input

Your input will be the dimensions of the lawn (two integers).

Output

Print the lawn and the mower in your chosen position. You may chose the four characters for grass, cut grass, mower front, and mower back. You only to need enough whitespace to show the current second's content to specs, but extra whitespace is completely allowed, as long as it looks the same.

Since this is an , you may either clear the output each second, or print enough newlines to appear to animate in the viewing frame (you may assume the viewing frame is the size needed to appear to animate).

A consistent time interval other than one second is allowed (i.e. 999 millis to save a byte, or two seconds for some reason), but it should be such that the lawn mower still appears to be moving naturally.

If possible, provide a visual (TIO, Snippet, GIF, etc.)

This is , so shortest answer in bytes wins.

Stephen

Posted 2017-05-15T12:41:31.667

Reputation: 12 293

3Nice challenge! Speaking from the perspective of a person who is annoyed by wires, you'd probably end up mowing over your wire :) – HyperNeutrino – 2017-05-15T12:59:21.690

May we assume that the output window is sized to fit the lawn? – Adám – 2017-05-15T13:07:42.680

Something else you might want to allow is returning a list of all the states, similar to your example run. – Adám – 2017-05-15T13:10:53.253

3

What if we like to mow our lawn the right way? https://s-media-cache-ak0.pinimg.com/736x/92/5c/7c/925c7ce055dcbf15467ccd2f4c975ac7.jpg

– tuskiomi – 2017-05-15T13:49:33.187

3@tuskiomi I've got another challenge in the works based on the same idea, but where the programmer has control over how it is mowed :) – Stephen – 2017-05-15T13:54:55.320

Not sure if I'll dig into this, but would it be acceptable to assume an ANSI terminal that accepts relative cursor positioning with Escape-sequences? – avl42 – 2017-06-21T16:18:02.027

@avl42 sure, go for it – Stephen – 2017-06-21T16:19:22.827

Answers

4

JavaScript (ES6/Node.js), 664 525 523 chars

f=(w,h)=>{Z=require('sleep');c=a=>console.log(a);X=1;Y=2;D='e';N='|';O={'|':[0,-1],'e':[1,0],'s':[0,1],'w':[-1,0]};S=[N,D,'s','w'];q=d=>F[Y+O[d][1]][X+O[d][0]];b=' '.repeat(w+4),U='  ';F=[b,b].concat([...Array(h)].map(x=>U+N.repeat(w)+U)).concat([b,b]).map(x=>x.split``);for(;;){f=F.map(a=>a.concat());f[Y][X]='@';d=O[D];f[Y-d[1]][X-d[0]]='=';c(f.map(x=>x.join``).join`\n`);if(F[Y][X]==N)F[Y][X]='.';d=O[D],f=q(D),R=S[(S.indexOf(D)+1)%4],r=q(R);(r==N)&&((f==' ')||(f=='.'))?D=R:(X+=d[0],Y+=d[1])
Z.msleep(1E3);c('\033[2J')}}

Unminified with comments:

f=(w,h)=>{
  Z = require('sleep');
  c=a=>console.log(a); 
  //mower coordinates
  X = 1;
  Y = 2;
  //mower direction
  D='e'; //n/e/s/w
  N='|';
  //directions with amount of change in [x,y] coordinates
  O = {'|':[0,-1],'e':[1,0],'s':[0,1],'w':[-1,0]};
  //direction short names
  S=[N,D,'s','w'];
  //query for item in specified direction relative to mower
  q=d=>F[Y+O[d][1]][X+O[d][0]];
 //generate field + whitespace
 b=' '.repeat(w+4),U='  ';
 F=[b,b].concat([...Array(h)].map(x=>U+N.repeat(w)+U)).concat([b,b]).map(x=>x.split``);
 for(;;){
    //print the field: 
    //make a copy of the field, so we can paste the mower on top of it
    f=F.map(a=>a.concat());
    //print mower head
    f[Y][X]='@';
    //print mower tail
    d = O[D];
    f[Y-d[1]][X-d[0]]='=';
    c(f.map(x=>x.join``).join`\n`);   
    //-----
    //move the mower
    if(F[Y][X]==N)F[Y][X]='.';//cut the grass if we stand on some
    d=O[D],//how many fields to move forward
        f=q(D),//item in front of mower
        R=S[(S.indexOf(D)+1)%4],//name of direction if we rotate to the right
        r=q(R);//item to right of mower
    //if there is wall in front of me OR cut grass in front of me and uncut on the right, turn right, else go ahead
    (r==N) && ((f==' ') || (f=='.'))?D=R:(X+=d[0],Y+=d[1])
    Z.msleep(1E3);
    c('\033[2J');
};
}
//test script
f(3,3);

note: I suppose I should get of the 'sleep' package and rewrite with setTimeout to be nodejs independent

Axarydax

Posted 2017-05-15T12:41:31.667

Reputation: 166

I tried sticking this into TIO (it says it works for node.js). Any clue why it isn't working?

– Stephen – 2017-05-30T20:43:11.513

because of the 'sleep' module - i'll get rid of it – Axarydax – 2017-06-01T10:44:26.003