A.I.: Find the princess in as few steps as possible - artificial-intelligence

I'm doing an Artificial Intelligence track at HackerRank and this is the first time I do this kind of programs.
On the first program, https://www.hackerrank.com/challenges/saveprincess/problem, I have to do the following:
Princess Peach is trapped in one of the four corners of a square grid.
You are in the center of the grid and can move one step at a time in
any of the four directions. Can you rescue the princess?
Input format
The first line contains an odd integer N (3 <= N < 100) denoting the
size of the grid. This is followed by an NxN grid. Each cell is
denoted by '-' (ascii value: 45). The bot position is denoted by 'm'
and the princess position is denoted by 'p'.
Grid is indexed using Matrix Convention
Output format
Print out the moves you will take to rescue the princess in one go.
The moves must be separated by '\n', a newline. The valid moves are
LEFT or RIGHT or UP or DOWN.
What should I do in these kind of problems?
Move to one corner and check if the princess is there, and it is not, move to another corner?
Here the goal is to do it in as few steps as possible but I think that will only happen if I'm lucky and I find the princess in the first corner to which I move.
I have thought that I could check if the princess is the corner I'm moving to before move to it, but I don't know if it is allowed in this problem.

Read the description of the input format (emphasis mine):
This is followed by an NxN grid. Each cell is denoted by '-' (ascii value: 45). The bot position is denoted by 'm' and the princess position is denoted by 'p'.
You do not have to actually go to each corner to see whether the princess is there, you already know where she is! Just determine the difference in position of the cells containing the bot m and the princess p and print the accordant movements. E.g., if the difference is 2 in x and -1 and y direction, you might go right right up.

What a boring problem... Seriously.
Load in the input data, starting with the grid size.
Accept lines of input corresponding to the grid size.
Since you know that the grid is a square, check the corners and move diagonally corresponding to what corner the princess is in.
Solution in 7 lines of python:
gridsize = int(input('Enter number of rows: '))
grid = [ input('Enter row: ') for r in range(gridsize) ]
move_dist = (gridsize-1)//2
if grid[ 0][ 0] == 'p': print('\n'.join([ 'UP\nLEFT'] * move_dist))
elif grid[ 0][-1] == 'p': print('\n'.join([ 'UP\nRIGHT'] * move_dist))
elif grid[-1][ 0] == 'p': print('\n'.join([ 'DOWN\nLEFT'] * move_dist))
elif grid[-1][-1] == 'p': print('\n'.join(['DOWN\nRIGHT'] * move_dist))

Related

How can I get the leftover room space?

So this is the task I need help with:
The blueprint of a house is made on a unit square grid sheet. All rooms must be rectangular. So far, N rooms have been drawn on the blueprint. Each room is defined by the upper left and lower right corners. One field of the square grid is given by the x and y coordinates, the coordinates of the upper left field (0,0). The x-coordinates increase horizontally and the y-coordinates increase vertically. The designer wants to calculate how many new rectangular rooms can be added if the two sides of any two new rooms cannot have a common part, and all four sides are adjacent or existing, or the side of the house. The rooms planned so far are such that every free space is rectangular. Make a program that tells you what the largest possible new room area can be in your plan.
Input:
The first line of the standard input has the number of rooms in the design (1≤N≤10,000) and the coordinates of the upper left (FX, FY) and lower right (AX, AY) corners of the house (0 ≤ FX < AX ≤ 1000, 0 ≤ FY < AY ≤ 1000), separated by a space. Each of the following N lines has coordinates (FX ≤ LFXi ≤ RAXi ≤ AX, FY ≤ LFYi ≤ RAYi ≤ AY) of the upper left (LFXi, LFYi) and lower right (RAXi, RAYi) of each room, separated by a space.
Output:
The first line of the standard output should be the area of ​​the largest new room!
Theres an example in the link and its the basic input and output that you can test the program with.
I translated this task from hungarian so the Példa=example , Bemenet=input , Kimenet=output. I would be really happy to get some help with this taks because for me it is a little bit too hard.
Basic input example

Finding optimal path (if exists)

Given the parameter k and an array [a0, a1, a2, a3, ..., an], where ax defines the height of the terrain, find the least amount of work you need to make the terrain passable. The terrain is passable that if the difference between two neighbouring places is smaller or equal to k. The height of the terrain at ax can be changed and the amount of work needed is equal to the difference in height you make. The height of a0 and an can't be changed and therefore some terrains may be completely unpassable.
I've been struggling with this for a while: This is what I figured out so far: Of course finding a solution (not taking the least amount of work needed into account) is easy - make 'steps' from a0 to an as in the diagram with k = 2 (red dots are the heights of the old terrain, grey for the new).
(The input for this particular terrain would be: k = 2, [0, 2, 3, 2, 5, 4, 5, 7])
As you can see, the new terrain doesn't take the old terrain into account and thus the work needed to transform the old one into this one can be huge.
Determining whether a path exists is trivial: k >= |a0-an|/n, but I have no idea about how would I go around in finding the optimal solution.
Use the simplex method to solve the following linear program.
minimize sum_i y_i
subject to
# y_i is notionally |x_i - a_i|
# equality holds in every optimal solution
y_i >= x_i - a_i for all i
y_i >= a_i - x_i for all i
# transformed terrain is passable, i.e., |x_i - x_{i+1}| <= k
x_i - x_{i+1} <= k for all i
x_{i+1} - x_i <= k for all i
One brute force solution is like this
For each element consider three next states, one with h + 1, h + 0, h - 1 where h is height of element. Now keep on traversing the array and see the following points
1)If the state has been arrived earlier discard it( so make bitmask dp for that )
2)If the you arrive at a state where traversed adjacent element diff is not k discard it.
3)If total work done till now is more than the minimum till found discard it.
Let be ht = an-a0 the total height. Let hAverageStep = ht/n. And k is the maximum step.
Ideally, at step 'i' the difference of height should be i*hAverageStep. In this case the path is just a constant straight. We want to get closer to this straight.
For the step 'i' you can observe if you need some "work" in this point to move it to the straight. If that work is greater than k, you must move also other points, for example some previous you have not worked enough.
If after moving every point as much as needed still 'an' is not reached, there's no solution.

Plotting arrays using a grouped horizontal bar graph

I am trying to generate a graph that should look similar to:
My arrays are:
Array4:[Nan;Nan;.......;20;21;22;23;24;..........60]
Array3:[[Nan;Nan;.......;20;21;22;23;24;..........60]
Array2:[0;1;2;3;4;5;6;Nan;Nan;Nan;Nan;17;18;.....60]
Array1:[0;1;2;3;4;5;6;Nan;Nan;Nan;Nan;17;18;.....60]
I cannot find the right way to group my arrays in order to plot them in the way shown on the above graph.
I tried using the following function explained in: http://uk.mathworks.com/help/matlab/ref/barh.html
barh(1:numel(x),y,'hist')
where y=[Array1,Array2;Array3,Array4] and x={'1m';'2m';'3m';......'60m'}
but it does not work.
Why Your Current Approach Isn't Working
Your intuition makes sense to me, but the barh function you are using doesn't work the way you think it does. Specifically, you are interpreting the meaning of the x and y inputs to that function incorrectly. Those are inputs are constant values, not entire axes. The first y input refers to the end-point of the bar that stretches horizontally from x = 0 and the first x input refers to location on the y-axis of the horizontal bar. To illustrate what I mean, I've provided the below horizontal bar graph:
You can find this same picture in the official documentation of the MATLAB barh function. The code used to generate this bar graph is also given in the documentation, shown below:
x = 1900:10:2000;
y = [57,91,105,123,131,150,...
170,203,226.5,249,281.4];
figure;
barh(x, y);
The individual elements of the x array, rather confusingly, show up on the y-axis as the starting locations of each bar. The corresponding elements of the y array are the lengths of each bar. This is the reason that the arrays must be the same length, and this illustrates that they are not specifications of the x and y axes as one might intuitively believe.
An Approach To Solve Your Problem
First things first, the easiest approach is to do this manually with the plot function and a set of lines that represent floating bars. Consult the official documentation for the plot function if you'd like to plot the lines with some sort of color coordination in mind - the code I present (modified version of this answer on StackOverflow) just switches the color of the floating bars between red and blue. I tried to comment the code so that the purpose of each variable is clear. The code I present below matches the floating bar graph that you want to be plotted, if you are alright with replacing thick floating bars with 2D lines floating on a plot.
I used the data that you gave in your question to specify the floating horizontal bars that this script would output - a screenshot is shown below the code. Array1 & Array2:[0;1;2;3;4;5;6;Nan;Nan;Nan;Nan;17;18;.....60], these arrays go from 0 to 6 (length = 6) and 17 to 60 (length = 60 - 17 = 43). Because there is a "discontinuity" of sorts from 7 to 16, I have to define two floating bars for each array. Hence, the first four values in my length array are [6, 6, 43, 43]. Where the first 6 and the first 43 correspond to Array1 and the second 6 and the second 43 correspond to Array2. Recognizing this "discontinuity", the starting point of the first floating bar for Array1 and Array2 is x = 0 and the starting point of the second floating bar for Array1 and Array2 is x = 7. Putting that all together, you arrive at the x-coordinates for the first four points in the floating_bars array, [0 0; 0 1.5; 17 0; 17 1.5]. The y-coordinates in this array only serve to distinguish Array1, Array2, and so on from each other.
Code:
floating_bars=[0 0; 0 1.5; 17 0; 17 1.5; 20 6; 20 7.5]; % Each row is the [x,y] coordinate pair of the starting point for the floating bar
L=[6, 6, 43, 43, 40, 40]; % Length of each consecutive bar
thickness = 0.75;
figure;
for i=1:size(floating_bars,1)
curr_thickness = 0;
% It is aesthetically pleasing to have thicker bars, this makes the plot look for like the grouped horizontal bar graph that you want
while (curr_thickness < thickness)
% Each bar group has two bars; set the first to be red, the second to be blue (i.e., even index means red bar, odd index means blue bar)
if mod(i, 2)
plot([floating_bars(i,1), floating_bars(i,1)+L(i)], [floating_bars(i,2) + curr_thickness, floating_bars(i,2) + curr_thickness], 'r')
else
plot([floating_bars(i,1), floating_bars(i,1)+L(i)], [floating_bars(i,2) + curr_thickness, floating_bars(i,2) + curr_thickness], 'b')
end
curr_thickness = curr_thickness + 0.05;
hold on % Make sure that plotting the current floating bar does not overwrite previous float bars that have already been plotted
end
end
ylim([ -10 30]) % Set the y-axis limits so that you can see more clearly the floating bars that would have rested right on the x-axis (y = 0)
Output:
How Do I Do This With the barh Function?
The short answer is that you'd have to modify the function manually. Someone has already done this with one of the bar graph plotting functions provided by MATLAB, bar3. The logic implemented in this modified bar3 function can be re-applied for your purposes if you read their barNew.m function and tweak it a bit. If you'd like a pointer as to where to start, I'd suggest looking at how they specify z-axis minimum and maximums for their floating bars on the plot, and apply that same logic to specify x-axis minimum and maximums for your floating bars in your 2D case.
I hope this helps, happy coding! :)
I explain here my approach to generate these type of graphs. Not sure if it is the best but it works and there is no need to do anything manually. I came up with this solution based on the following Vladislav Martin's explained fact: "The y-coordinates in this array only serve to distinguish Array1, Array2, and so on from each other".
My original arrays are:
Array4=[Nan....;20;21;22;23;24;..........60]
Array3=[Nan....;20;21;22;23;24;..........60]
Array2=[0;1;2;3;4;5;6;Nan;Nan;Nan;Nan;17;18;.....60]
Array1=[0;1;2;3;4;5;6;Nan;Nan;Nan;Nan;17;18;.....60]
x={'0m';'1m';'2m';'3m';'4m';....'60m'}
The values contained in these arrays make reference to the x-axis on the graph. In order to make the things more simple and to avoid having to code a function to determine the length for each discontinuity in the arrays, I replace these values for y-axis position values. Basically I give to Array1 y-axis position values of 0 and to Array2 0+0.02=0.02. To Array3 I give y-axis position values of 0.5 and to Array4 0.5+0.02=0.52. In this way, Array2 will be plotted on the graph closer to Array1 which will form the first group and Array4 closer to Array3 which will form the second group.
Datatable=table(Array1,Array2,Array3,Array4);
cont1=0;
cont2=0.02;
for col=1:2:size(Datatable,2)
col2=col+1;
for row=1:size(Datatable,1)
if isnan(Datatable{row,col})==0 % For first array in the group: If the value is not nan, I replace it for the corresponnding cont1 value
Datatable{row,col}=cont1;
end
if isnan(Datatable{row,col2})==0 % For second array in the group: If the value is not nan, I replace it for the corresponnding cont2 value
Datatable{row,col2}=cont2;
end
end
cont1=cont1+0.5;
cont2=cont2+0.5;
end
The result of the above code will be a table like the following:
And now I plot the Arrays using 2D floating lines:
figure
for array=1:2:size(Datatable,2)
FirstPair=cell2mat(table2cell(Datatable(:,array)));
SecondPair=cell2mat(table2cell(Datatable(:,array+1)));
hold on
plot(1:numel(x),FirstPair,'r','Linewidth',6)
plot(1:numel(x),SecondPair,'b','Linewidth',6)
hold off
end
set(gca,'xticklabel',x)
And this will generate the following graph:

Find largest square in matrix that can move from one corner to the other

You have a matrix of 0 and 1 for example:
1 1 1 0
1 1 1 0
1 1 1 0
1 1 1 1
0 1 1 1
1 0 1 1
A square is placed at position (0,0), find the size of the largest square of all 1s that be move from the upper left corner to the lower right corner. The square can only move down and to the right and only over elements which are 1.
In this example the size of the largest square is 2. The indexes of elements in the square are (0,0), (0,1), (1,0), (1,1).
I'm not sure how to solve this problem. I think first, you need to find the all the squares in the upper left corner and all squares in lower right corner. If the move is possible, then there must be squares in these 2 positions that are the same size. Then only attempt to move squares in the left corner that are equal in size to square in right corner. But I'm not sure how to go about finding the squares and checking if they can be moved.
You can use dynamic programming.
Let's assume that max_size(i, j) is the size of the largest square that can stay in a (i, j) cell(possibly 0)(stays in means that its top left corner is located in this cell). We can compute this value in a naive way(by iteratively increasing the size of the square and checking that it does not touch any 0). If a naive solution is not feasible, we can use binary search over the answer and prefix sums to get an O(log n) time per cell.
Let's say that f(i, j) is the largest square that can reach the (i, j) cell. The base case: f(0, 0) = max_size(0, 0)(we can always reach the the top left corner). For the other cells, it can be computed in the following way(I omit corner cases here):
for i <- 0 ... n - 1:
for j <- 0 ... m - 1:
f(i, j) = min(max_size(i, j), max(f(i - 1, j), f(i, j - 1)))
The answer is the largest f(i, j) such that i + f(i, j) - 1 = n - 1 and j + f(i, j) - 1 = m - 1.
The time complexity is O(n * m * log(min(n, m))).
Your first step is right: find the largest square that fits into both the lower right and the upper left.
Then, start with a square of that size in the upper left. Try the paths to the lower right breadth-first. After each step, you check whether the square still fits, otherwise reduce its size. You will then often arrive at a given place from two directions (from above and from the left). Continue from there with the bigger size (this unification step is why you should go breadth-first, this is also called "dynamic programming").
In your example, you start with an array of size 2 at (0 0), but let's say that you start with size 3 for demonstration purposes. So, layer 0 is a single square of size 3 at (0 0). Moving down is no problem, but moving to the right steps on some zeroes, so you have to reduce the size. Layer 1 is thus a list of two squares: one of size 3 at (1 0) and one of size 2 at (0 1). Next layer: move right from (0 1), need to reduce to size 1 at (0 2); move down from (0 1) as well as right from (1 0), both arrive at (1 1), from above with size 2, from left needs to reduce to size 2, so size 2; move down from (1 0), reduce to size 2. So, Layer 2 is a list of three squares: one of size 2 at (2 0), one of size 2 at (1 1), and one of size 1 at (0 2). I think this suffices as a demonstration.
You have reached a solution when you complete a layer that contains a square that touches the lower right. You can tell that there is no solution when all your squares are size 0.
Brute force solution
If your matrix has size N x M, every path of a square of size S x S from top left to bottom right is N + M - 2S 'steps' (movements to the right or left) long, where N - S steps will go downwards and M - S steps rightwards. So if we disregard the values on the matrix, there will be (N + M - 2S) choose (N - S) possible paths.
So if the matrix isn't too large, it might be feasible to just try all these paths for a given square size S and test them for compliance with the square placement rules (whether in each step, the square only covers 1s and no 0s.)
Do this for each S from 1 to min(N,M), and keep track of the values of S for which you can find at least one valid path.
Then, just take the maximum of these S values and you've got the wanted result.
So brute-forcing will (eventually) give you the correct value.
Optimizations
Off course, this isn't as efficient as could be, which will lead to enormous runtimes for large matrices. But we can improve step by step, by looking into what steps are unneccesary.
One valid path for a given square size suffices
If you've found a valid path for a given square size S, you don't have to look for more paths for the same square size and can skip to testing other, yet untested square sizes.
One invalid step kills the whole path
If any step of a path leads to an invalid placement, you don't have to check the other steps. You already know you can't use the whole path.
Don't do double work
Each of the (N-S) * (M-S) possible placements of a square with given size S will be part of several paths. Instead of checking each placement's validity for each path it is part of, do it just once for each placement and store the result in a (N-S) x (M-S) matrix.
Bigger won't fit better
If you've tested all paths for a given square size S, and none of them was valid, you don't have to test larger S at all, as you know there won't be valid paths for them.
Smaller won't fit worse
If you've found a path for a given square size S, you can be sure that all smaller square sizes will have at least one valid path, too, so you don't have to test them. (You wouldn't have to, anyway, as you're looking for the maximum S with at least one valid path.)
Bisection?
Combining the two realizations above, you'll come to the conclusion that it won't be optimal to test sizes S in order, be it increasing or decreasing. Rather, you could start somewhere in-between and —depending on the result for that S— rule out all smaller or all larger values for S. Whether it is optimal to start exactly in the middle (at min(N,M) / 2), I'm not sure, though, as the number of paths to search for a given S (remember the binomial coefficient formula in the "Brute force" section above) depends on the size of S.
Parallelization
Almost every level of the brute force algorithm has several steps that are independent of each other and could be executed in parallel.
More?
I'm sure even with all of the above implemented, there's still room for more optimization, even if I can't think of any right now.

How to calculate distance between 2 points in a 2D matrix

I am both new to this website and new to C. I need a program to find the average 'jumps' it takes from all points.
The idea is this: Find "jump" distance from 1 to 2, 1 to 3, 1 to 4 ... 1 to 9, or find 2 to 1, 2 to 3, 2 to 4 2 to 5 etc.
Doing them on the first row is simple, just (2-1) or (3-1) and you get the correct number. But if I want to find the distance between 1 and 4 or 1 to 8 then I have absolutely no idea.
The dimensions of the matrix should potentially be changeable. But I just want help with a 3x3 matrix.
Anyone could show me how to find it?
Jump means vertical or horizontal move from one point to another. from 1 to 2 = 1, from 1 to 9 = 4 (shortest path only)
The definition of "distance" on this kind of problems is always tricky.
Imagine that the points are marks on a field, and you can freely walk all over it. Then, you could take any path from one point to the other. The shortest route then would be a straight line; its length would be the length of the vector that joins the points, which happens to be the difference vector among two points' positions. This length can be computed with the help of Pythagora's theorem: dist = sqrt((x2-x1)^2 + (y2-y1)^2). This is known as the Euclidian distance between the points.
Now imagine that you are in a city, and each point is a building. You can't walk over a building, so the only options are to go either up/down or left/right. Then, the shortest distance is given by the sum of the components of the difference vector; which is the mathematical way of saying that "go down 2 blocks and then one block to the left" means walking 3 blocks' distance: dist = abs(x2-x1) + abs(y2-y1). This is known as the Manhattan distance between the points.
In your problem, however, it looks like the only possible move is to jump to an adjacent point, in a single step, diagonals allowed. Then the problem gets a bit trickier, because the path is very irregular. You need some Graph Theory here, very useful when modeling problems with linked elements, or "nodes". Each point would be a node, connected to their neighbors, and the problem would be to find the shortest path to another given point. If jumps had different weights (for instance, is jumping in diagonal was harder), an easy way to solve this is would be with the Dijkstra's Algorithm; more details on implementation at Wikipedia.
If the cost is always the same, then the problem is reduced to counting the number of jumps in a Breadth-First Search of the destination point from the source.
Let's define the 'jump' distance : "the number of hops required to reach from Point A [Ax,Ay] to Point B [Bx,By]."
Now there can be two ways in which the hops are allowed :
Horizontally/VerticallyIn this case, you can go up/down or left/right. As you have to travel X axis and Y axis independently, your ans is:jumpDistance = abs(Bx - Ax) + abs(By - Ay);
Horizontally/Vertically and also Diagonally
In this case, you can go up/down or left/right and diagonally as well. How it differs from Case 1 is that now you have the ability to change your X axis and Y axis together at the cost of only one jump . Your answer now is:jumpDistance = Max(abs(Bx - Ax),abs(By - Ay));
What is the definition of "jump-distance" ?
If you mean how many jumps a man needs to go from square M to N, if he can only jumps vertically and horizontally, one possibility can:
dist = abs(x2 - x1) + abs(y2 - y1);
For example jump-distance between 1 and 9 is: |3-1|+|3-1| = 4
There are two ways to calculate jump distance.
1) when only horizontal and vertical movements are allowed, in that case all you need to do is form a rectangle in between the two points and calculate the length of two adjacent side. Like if you want to move from 1 to 9 then first move from 1 to 3 and then move from 3 to 9. (Convert it to code)
2) when movements in all eight directions are allowed, things get tricky. Like if you want to move from 1 to 6 suppose. What you'll need to do is you'll have to more from 1 to 5. And then from 5 to 6. The way of doing it in code is to find the maximum in between the difference in x and y coordinates. In this example, in x coordinate, difference is 2 (3-1) and in y coordinate, difference is 1 (2-1). So the maximum of this is 2. So here's the answer. (Convert to code)

Resources