Go to opposite corner of rectangle in all directions - Harder

17

This is essentially the same thing as this question, except harder. You are again to write a program that gets from the lower-left corner of a rectangle to the upper-right corner. However, this time diagonal moves are allowed.

The program will accept an ordered pair (width, height), and use these as the dimensions for a rectangle. Your program will then create an ASCII-art of the solution (use . for an empty square, # for part of the solution, and X for starting square) and count the number of moves it takes to reach the endpoint.

Example

Input: (5, 6)

Output:

....#
....#
...#.
..#..
.#...
X....
Move count: 5

Shortest answer in bytes wins!

ericw31415

Posted 2016-04-03T12:03:18.933

Reputation: 2 229

7It isn't, the solutions will require LOTS of editing – Blue – 2016-04-03T12:21:52.423

4This challenge, like the suggested duplicate, is a trivially simple problem that is non-trivial to golf, which is a great combination. Despite the similarity, this challenge requires a different approach and well golfed solutions to the previous challenge cannot be trivially amended to be competitive here. – trichoplax – 2016-04-03T12:30:04.110

It could do with a more distinguishing title though... – trichoplax – 2016-04-03T12:33:57.147

yeah, any ideas? – ericw31415 – 2016-04-03T12:42:15.630

@CoolestVeto This will actually be a great deal harder, since in that one, diagonal movements are not allowed. – ericw31415 – 2016-04-03T12:43:27.370

Close-voters, think why you want to close it. Then justify it. Then try to counter your justification. If you still think it should be closed, comment with your justification. If the justification doesn't hold up, please retract your vote. If it does hold up, please vote to reopen when it is fixed. – wizzwizz4 – 2016-04-03T12:45:04.023

By the way, that other question was also created by me. I based this one off of that one, but the answers will most likely be totally different. – ericw31415 – 2016-04-03T12:50:43.313

I think this is a great challenge. IMO it's much harder than the last one. – James – 2016-04-03T15:15:43.110

@ericw31415 What are the minimum values of the two input numbers? – Luis Mendo – 2016-04-03T15:32:24.117

1@LuisMendo The minimum is the smallest possible grid; 1 by 1. – ericw31415 – 2016-04-03T16:01:00.280

Answers

1

MATL, 38 bytes

'.#X'!iSPXytf0)Jh1w(tzqDQI1()Gd0<?!]XP

Try it online!

Explanation

Let m and n be the sorted inputs, such that m is greater than or equal to n. The code initially builds an mxn matrix as follows:

  • Value 2 along the main diagonal, and on the lower part of the last column. This corresponds to character #. The number of these entries minus 1 is the move count.
  • Value 3 at entry (1,1), corresponding to the X.
  • The remaining entries contain 1, corresponding to character .

If needed, the matrix is now transposed so that it has the desired shape. Note that the first dimension of a matrix is its height, not width, so it corresponds to the second input.

The matrix is then flipped upside down so that X appears at the bottom of the first column, and its entries are used as indices into the string '.#X' to produce the desired 2D char array.

'.#X'    % push this string
!        % transpose into a column
i        % input array
SP       % sort it in non-increasing order
Xy       % identity matrix with that size: fill diagonal with 1, rest entries are 0
tf0)     % linear index of last 1
Jh       % append 1j (imaginary unit): linear index of lowest part of last column
1w(      % fill those entries with 1
tzq      % duplicate. Number of nonzero entries minus 1: this is the move count
D        % display move count (and remove it from the stack)
Q        % add 1. Matrix now contains values 1 and 2
I1(      % set first entry (in linear order) to value 3
)        % use matrix as index into the initial string. Gives 2D char array
Gd0<     % push input array again. Is it decreasing?
?        % if so
  !      %   transpose char array
]        % end
XP       % flip upside down. Implicitly display

Luis Mendo

Posted 2016-04-03T12:03:18.933

Reputation: 87 464

1It doesn't say the move count...? – ericw31415 – 2016-04-03T16:03:36.967

@ericw31415 Sorry. Solved now – Luis Mendo – 2016-04-03T16:13:20.300

5

Pyth, 46 45 44 bytes

eSKtMQjsM_mm?sJ,kd?q#J.umtWbbNeSKK\#\.\XhQeQ

Try it here.

Explanation:

move-count-printing:

  K     assign K to...
     Q  the input, a 2-length array...
   tM   with each element decremented
eS      take the max and output it (this is the number of moves)


main path-finding logic:

    mm                     hQeQ  map over x-values and y-values...
        J,kd                     assign J to [x,y]
      ?s                         if both x and y are NOT zero (sum is truthy)...
            ?q#J[...]              if [x,y] is present in [...] (see below)...
                     \#            ... put a # at this position in the output
                       \.          ... else, put a . at this position
                         \X      ... else, put the X here (at [0,0])
jsM_                             reverse and output in the proper format


the [...] part in the code above, which finds positions where #s go:

.u      eSKK  cumulative reduce on <number of moves> elements, starting at K,
                which is [max_x, max_y] as assigned at the beginning
  m    N      map over x and y...
   tWbb       decrement, only if the value is > 0

Doorknob

Posted 2016-04-03T12:03:18.933

Reputation: 68 138

2

JavaScript (ES6), 132

Edit 2 bytes saved thx @Neil

(w,h)=>[...Array(--h)].map((_,i)=>R(w-i)+'#'+R(i),--w,R=(n,c='.')=>c.repeat(n>w?w:n>0&&n)).join`
`+`
x${R(w-h,'#')+R(h)}
`+(h>w?h:w)

Test

f=(w,h)=>[...Array(--h)].map((_,i)=>R(w-i)+'#'+R(i),--w,R=(n,c='.')=>c.repeat(n>w?w:n>0&&n)).join`
`+`
x${R(w-h,'#')+R(h)}
`+(h>w?h:w)

function test() {
  var w,h
  [w,h]=I.value.match(/\d+/g)
  O.textContent=f(w,h)
}  

test()
Test <input id=I value="4 5"><button onclick="test()">-></button>
<pre id=O></pre>

edc65

Posted 2016-04-03T12:03:18.933

Reputation: 31 086

Save 2 bytes by moving the w--,R=... into the map(). – Neil – 2016-04-03T18:40:27.043

0

Python 3, 161 156 bytes

def f(w,h):
 x=[['.']*w for i in[0]*h];i=0
 while i<w or i<h:x[~min(i,h-1)][min(i,w-1)]=['#','X'][i<1];i+=1
 for i in x:print(''.join(i))
 print(max(w,h)-1)

A function that takes input via argument and prints the ascii-art, followed by the move count, to STDOUT.

How it works

The program first creates a list of lists, where each list represents one row of the grid and each element of the component lists is .. Each element that should be # has the property that if the output grid was square, the ordinates representing its location would be equal; hence, looping over some index i and inserting # at location (i, i) would give the desired output. However, the grid is not always square, and thus the indices are clamped to the grid by taking the minimum of the index and width/height (decremented due to zero-indexing) as required. If the index is zero, the current position must be the bottom-left entry, and thus X is instead inserted. Next, the elements in each line are concatenated, and each line is printed to STDOUT. The number of moves is the maximum of the width/height decremented; this is also printed.

Try it on Ideone

TheBikingViking

Posted 2016-04-03T12:03:18.933

Reputation: 3 674

0

Javascript (using external library) (235 bytes)

Jeez this was hard! Well...my library wasn't really the right task for this haha. But I liked the challenge

(x,y)=>{r=x-1;s=y-1;m=Math.max(r,s);n=Math.min(r,s);l=_.RangeDown(s,y).WriteLine(z=>_.Range(0,x).Write("",w=>z==0&&w==0?"X":(z==w||(z==s&&w>=n)||(w==r&&z>=n))?"#":"."));return l+"\r\nMove count: "+(l.length-l.split("#").join("").length)}

Link to lib: https://github.com/mvegh1/Enumerable

Code explanation: Create function of 2 variables. Store x-1 and y-1 into variables. Store max and min of those into variables. Create a vertically descending range of numbers from (y-1) for a count of y. For each element on the vertical range, write a line for the current element, according to the complex predicate. That predicate creates an ascending range of integers from 0, for a count of x. For each element in that range, concatenate into 1 string according to a complex predicate. That predicate checks if on bottom left, else checks if on diagonal, else checks we're at X or Y border. Finally, all of that was stored in a variable. Then to get the move count, we basically just count the #'s. Then concatenate that to the stored variable, and return the result

That was a mouthful haha. The screenshot has the wrong bytecount because I found a way to save 4 bytes while posting this

EDIT: I see other answers aren't putting "Move count: " in their output, but mine is. If that isn't a requirement, that shaves a bunch of bytes...

enter image description here

applejacks01

Posted 2016-04-03T12:03:18.933

Reputation: 989