I'm trying to solve this problem:
1 2 3
4 5 6
7 8 9
* 0 #
Given a starting number, find all 6-digit numbers possible, numbers can only be dialed horizontally or vertically. Repetitions not allowed. Number can't start from zero and doesn't include * and #. For example, if last dialed number is 3, the next one could be 1, 2, 6 or 9.
I'm trying this making by creating a graph, in which a number has only those numbers adjacent which are in the same row and column, and then finding all possible paths of length 5 from the starting number. But I don't know any algorithm for doing that yet..
Any suggestions?
Assume the numbers are stored in a 2-d array NUMPAD, where "1" is at index [0][0], "2" is at index [0][1], etc.
Func permute_nums(digits_so_far)
If digits_so_far has 6 elements
print digits_so_far
return
Let L = last element of digits_so_far
Find index (x,y) of L in NUMPAD
For i from -2 to +2
if (x+i,y) is NOT out of bounds
Find number n at (x+i,y)
permute_nums(digits_so_far + [n])
if (x,y+i) is NOT out of bounds
Find number m at (x,y+i)
permute_nums(digits_so_far + [m])
Given the starting digit s, do permute_nums([s])
I think you're on the right path.
Just traverse the tree (mark every visited node, to avoid repetitions), and output every path of length 5.
You don't really need anything new here, even a basic Breadth first search that is limited to depth 5 will do.
hmmm. That should be pretty easy.
static var a:Array=[[8],[2,4],[1,3,5],[2,6],[1,5,7],[2,4,6,8],[3,5,9],[4,8],[5,7,9,0],[6,8]];
function giveAllnumbers(numbersSoFar:String,lastSelectedNumber:int,:int) {
if (howManyToSelectLeft==0) {
trace(numbersSoFar); // output goes here
return;
}
for (var i:int=a[lastSelectedNumber].length-1;i>=0;i--)
giveAllNumbers(numbersSoFar+a[lastSelectedNumber][i].toString(),
a[lastSelectedNumber][i],
howManyToSelectLeft-1);
}
This is Actionscript, but can be accommodated to any other language. Invoke with giveAllNumbers(''+yourNumber.toString(),yourNumber,desiredLength);
This problem can be solved recursively, and the returning point will be when length == 6.
private static void countMaxNumbers(String i) {
if(i.length() == 6)
{
numberCount++;
return;
}
if(i.charAt(i.length() - 1) == '1'){
countMaxNumbers(i+'2');
countMaxNumbers(i+'3');
countMaxNumbers(i+'4');
countMaxNumbers(i+'7');
}
else if(i.charAt(i.length() - 1) == '2'){
countMaxNumbers(i+'5');
countMaxNumbers(i+'8');
countMaxNumbers(i+'0');
countMaxNumbers(i+'1');
countMaxNumbers(i+'3');
}
else if(i.charAt(i.length() - 1) == '3'){
countMaxNumbers(i+'1');
countMaxNumbers(i+'2');
countMaxNumbers(i+'6');
countMaxNumbers(i+'9');
}
else if(i.charAt(i.length() - 1) == '4'){
countMaxNumbers(i+'1');
countMaxNumbers(i+'7');
countMaxNumbers(i+'5');
countMaxNumbers(i+'6');
}
else if(i.charAt(i.length() - 1) == '5'){
countMaxNumbers(i+'2');
countMaxNumbers(i+'8');
countMaxNumbers(i+'0');
countMaxNumbers(i+'4');
countMaxNumbers(i+'6');
}
else if(i.charAt(i.length() - 1) == '6'){
countMaxNumbers(i+'3');
countMaxNumbers(i+'9');
countMaxNumbers(i+'4');
countMaxNumbers(i+'5');
}
else if(i.charAt(i.length() - 1) == '7'){
countMaxNumbers(i+'1');
countMaxNumbers(i+'4');
countMaxNumbers(i+'8');
countMaxNumbers(i+'9');
}else if(i.charAt(i.length() - 1) == '8'){
countMaxNumbers(i+'7');
countMaxNumbers(i+'9');
countMaxNumbers(i+'2');
countMaxNumbers(i+'5');
countMaxNumbers(i+'0');
}else if(i.charAt(i.length() - 1) == '9'){
countMaxNumbers(i+'3');
countMaxNumbers(i+'6');
countMaxNumbers(i+'7');
countMaxNumbers(i+'8');
}else if(i.charAt(i.length() - 1) == '0'){
countMaxNumbers(i+'2');
countMaxNumbers(i+'8');
countMaxNumbers(i+'5');
}
}
Answer should be : 12855
Related
Problem statement =>
You are given queries. Each query consists of a single number N. You can perform any of the 2 operations on in each move:
1: If we take 2 integers a and b where N=a*b (a>1,b>1), then we can change N=max(a,b).
2: Decrease the value of N by 1.
Determine the minimum number of moves required to reduce the value of N to 0.
here is the link for better understanding.
https://www.hackerrank.com/challenges/down-to-zero-ii/problem
I know here are some overlapping sub-problems and we can use DP to ignore the computation of same sub-problems again and again.
Now, my question is how in this problem, same sub-problems have same solutions. Because we have to solve this from top to bottom and sub-problem have same solution if we solved them from bottom to top.
For example
N=4
1 possibility = 4->3->2->1->0
2 possibility = 4->2->1->0
Now in above two possibility, 2 is repeating and I can use DP, but how I store their values. I mean, in 1 possibility solution of 2 is different from 2nd possibility because in first one I've to traverse 4->3->2 here solution of 2 is 2 and in 2nd possibility we traverse 4->2 and solution of 2 here is 1 now these 2 same sub-problems have different values because of the solving from top to bottom. Now I'm totally confused here. Please someone help me out in this.
The solution for a number N should store the minimun steps required to make it 0
this is how the sol should look
int dp[1000001];
memset(dp,-1,sizeof(dp);
int sol(N){
if(N == 2){
return 2;
}
if(dp[n]!=-1){
return dp[n]'
}
int sol = 1+sol(min(move1,move2));
dp[n] = sol ;
return sol;
}
EDIT 2:
I think this is a solution for your problem. The solution is in JavaScript:
// ****************************************************************************
function findPaths(tree, depth = 0, path = [], paths = [-1, []]) {
const [node, children] = tree
path.push(node)
if (!children) {
// console.log(path, depth)
if (paths[0] === -1 || paths[0] > depth) {
paths[0] = depth
paths[1] = [paths.length]
} else if (paths[0] === depth) {
paths[1].push(paths.length)
}
paths.push([...path])
path.pop()
return
}
children.forEach((el) => {
findPaths(el, depth + 1, path, paths)
})
path.pop()
return paths
}
// ****************************************************************************
function downToZero(n) {
const tree = [n]
const divisors = []
for (let i = 2; i <= Math.sqrt(n); i++) {
if (n % i == 0) {
divisors.push(Math.max(i, n / i))
}
}
if (divisors.length) {
tree.push(divisors.map(downToZero))
} else if (n > 0) {
tree.push([downToZero(n - 1)])
}
return tree
}
// ****************************************************************************
function printPaths(paths) {
console.log('Total number of solutions:', paths.length - 2)
console.log('Total number of solutions with minimal moves:', paths[1].length)
console.log('Minimal moves:', paths[0])
paths[1].forEach((pathIndex) => {
let printPath = ''
paths[pathIndex].forEach((element) => {
printPath = `${printPath}${printPath === '' ? '' : '->'}${element}`
})
console.log(printPath)
})
console.log('')
}
// ****************************************************************************
// Test
printPaths(findPaths(downToZero(812849)))
printPaths(findPaths(downToZero(100)))
printPaths(findPaths(downToZero(19)))
printPaths(findPaths(downToZero(4)))
Given two strings, A and B, of equal length, find whether it is possible to cut both strings at a common point such that the first part of A and the second part of B form a palindrome.
I've tried bruteforce, this can be achieved in O(N^2). I'm looking for any kind of optimization. I'm not familiar with back tracking and DP. So, can anyone throw some light....whether i should think in these lines?
Here is a possible solution considering that we cut the 2 strings in a common point. It runs in linear time w.r.t the string length, so in O(n).
// Palindrome function
function is_pal(str) {
str_len = len(str)
result = true
for i from 0 to 1 + str_len / 2 {
if str[i] != str[str_len - i] then {
result = false
break
}
}
return result
}
// first phase: iterate on both strings
function solve_pb(A, B) {
str_len = len(A)
idx = 0
while A[idx] == B[str_len - idx - 1] {
idx += 1
}
if idx >= str_len / 2 {
return str_len / 2
else if is_pal(A[idx + 1 ... str_len - idx - 2]) {
return str_len - idx - 2
else if is_pal(B[idx + 1 ... str_len - idx - 2]) {
return idx
else
return -1 // no solution possible
The principle is the following:
First, we iterate on A, and reverse iterate on B, as long as they are 'symetric'.
A: aaabcaabb ............ // ->
B: ............ bbaacbaaa // <-
If the strings are symetric until their respective middle, then the solution is trivial. Otherwise we check if the 'middle portion' of A or B is itself a palindrome. If it is the case we have a solution, otherwise we do not have a solution.
I have a two dimensional matrix like
A.........
##....##..
.####...##
..........
.......###
B.........
####...###
#...#.###.
Where '.' represents path and '#' represents wall.I have to find the shortest path possible from point A to point B.I am familiar with BFS algorithm and it seems like a reasonable algorithm for the problem. But I find it confusing to apply on the grid.Can anyone suggest implementation of BFS algorithm in this problem with some pseudo-codes ?
The BFS algorithms is basically:
1.Enqueue the source vertex and mark it visited.
2.While the Q is not empty repeat 3 and 4.
3. Perform deque and the for the dequed vertex x, do
4. For all adjacent vertices of x, that are not visited and mark them visited and enqueue them to the Q.
So thats the basic algorithm, if we go step by step its very easy to apply these steps to grid,the only thing that we should be careful is for a cell in a grid there are 8 neighbours possible, and we must check the boundary conditions before traversing the neighbours, to avoid array index out of bounds.
Say we are at position A(a,b) and we want to reach B(c,d). We follow the similar 4 steps but with some modification as follows:
1.Make a Q of 2-d points,(You can do that easily in languages like Java, by making a class of 2-d points and then Q of objects of that class)
2.Make a 2-d array visited of size of grid of type boolean, initialized to false.
3.Make a 2-d array distance of size of grid of type integer, that will be used for the distance.
Let size of grid be nxm
Now the pseudocode is as follows:
Enqueue A(a,b) to the Q
Mark dist[a][b] = 0 and visited[a][b] = true
while( Q is not empty )
{
Point p = deque(Q)
if( p matches B(c,d) )
{
print( Yes path is possible from A to B with distance[c][d] )
return
}
else
{
//Now all we have to do is check all the possible neighbour cells according
// to our current position in the grid
// So we have to check all the 8 neighbour cells
if(p.y < m - 1)
{
if( grid[p.x][p.y + 1] != '#' and visited[p.x][p.y + 1] == false )
{
enqueue (p.x,p.y + 1) to the Q // step s1
distance[p.x][p.y + 1] = distance[p.x][p.y] + 1 // step s2
visited[p.x][p.y + 1] = true // step s3
}
}
if(p.x < n - 1)
{
if( grid[p.x + 1][p.y] != '#' and visited[p.x + 1][p.y] == false )
{
Repeat steps s1,s2,s3 for point (p.x + 1,p.y)
}
}
if(p.y > 0)
{
if( grid[p.x][p.y - 1] != '#' and visited[p.x][p.y - 1] == false )
{
Repeat steps s1,s2,s3 for point (p.x,p.y - 1)
}
}
if(p.x > 0)
{
if( grid[p.x - 1][p.y] != '#' and visited[p.x - 1][p.y] == false )
{
Repeat steps s1,s2,s3 for point (p.x - 1,p.y)
}
}
if(p.x > 0 and p.y > 0)
{
if( grid[p.x - 1][p.y - 1] != '#' and visited[p.x - 1][p.y - 1] == false )
{
Repeat steps s1,s2,s3 for point (p.x - 1,p.y - 1)
}
}
if(p.x > 0 and p.y < m-1)
{
if( grid[p.x - 1][p.y + 1] != '#' and visited[p.x - 1][p.y + 1] == false )
{
Repeat steps s1,s2,s3 for point (p.x - 1,p.y + 1)
}
}
if(p.x < n-1 and p.y > 0)
{
if( grid[p.x + 1][p.y - 1] != '#' and visited[p.x + 1][p.y - 1] == false )
{
Repeat steps s1,s2,s3 for point (p.x + 1,p.y - 1)
}
}
if(p.x < n-1 and p.y < m-1)
{
if( grid[p.x + 1][p.y + 1] != '#' and visited[p.x + 1][p.y + 1] == false )
{
Repeat steps s1,s2,s3 for point (p.x + 1,p.y + 1)
}
}
}
}
print( the path is not possible )
Very basically, think of every dot (.) as a node, and every two dots that are neighbors should also have an edge between them*. This way you get a graph that has all possible places that the path can go through, and it only includes valid edges.
From there it's pretty easy to run BFS...
* If you are allowed to move diagonally, then those edges should also be added. This is already getting into what exactly is the definition of a "neighbor".
I came across this question, where the OP wanted to improve the following if-block. I open this as a new question because I'm searching a more general solution to this kind of problem.
public int fightMath(int one, int two) {
if(one == 0 && two == 0) { result = 0; }
else if(one == 0 && two == 1) { result = 0; }
else if(one == 0 && two == 2) { result = 1; }
else if(one == 0 && two == 3) { result = 2; }
else if(one == 1 && two == 0) { result = 0; }
else if(one == 1 && two == 1) { result = 0; }
else if(one == 1 && two == 2) { result = 2; }
else if(one == 1 && two == 3) { result = 1; }
else if(one == 2 && two == 0) { result = 2; }
else if(one == 2 && two == 1) { result = 1; }
else if(one == 2 && two == 2) { result = 3; }
else if(one == 2 && two == 3) { result = 3; }
else if(one == 3 && two == 0) { result = 2; }
else if(one == 3 && two == 1) { result = 1; }
else if(one == 3 && two == 2) { result = 3; }
else if(one == 3 && two == 3) { result = 3; }
return result;
}
Now there are n^k possibilities to get a result, where n = 2 and k = 4.
Some answers are suggesting to use an multi-array as a table to reduce the if-jungle.
But I would like to know how to solve such a problem with big n and k? Because a solution with if, switch and the suggested array approach will not scale well and to type things like that in code should be avoided.
If I think about combinatoric problems, there have to be a way to evaluate them easy.
It's just a table of data. The answer to the question is found by multiple keys. It is no different to returning some data held in a database table which could itself be huge and perhaps span multiple tables.
There are two ways to solve this:
Data-based. For example you could create a HashMap mapping the pair of values to the result.
class Pair {
int one, two;
//Generate hashcode and equals
}
Map<Pair, Integer> counts = new HashMap<>();
Pattern-based. Identify a rule/formula that can be used to determine the new value.
This is obviously better but relies on being able to identify a rule that covers all cases.
I would like to know how to solve such a problem with big n and k.
Since the output is determined arbitrarily (a game designer's whims) instead of mathematically (a formula), there's no guarantee of any pattern. Therefore the only general solution is some kind of lookup table.
Essentially, the question is similar to asking for a program that does f(a,b) -> c mapping, but you don't know any of the data beforehand -- instead it's provided at runtime. That program could process the data and find a pattern/formula (which might not exist) or it could build a lookup table.
Personally, I think it's clearer to change the logic to operate on intent (so reading the code explains how the attack works) instead of the actual outcomes (enumerating the list of inputs and matching outputs). Instead of building an if-jungle or a lookup table, structure your code based on how you want the logic to work. JAB's enum-based solution expresses the fight logic explicitly which makes it easier to see where to add new functionality and easier to see bugs (an off by one error in a lookup table isn't obviously wrong on inspection). A lookup table is a likely optimization, but that's only necessary if a profiler says so.
Looking at your question and the original one there appears to be no deducible pattern between the input from the two players and the output (perhaps I'm wrong). Given this the only options are the "if-jungle" you mention or to use a data structure.
To solve such a problem for big n and k values my suggestion would be to create a rule to determine the output (either none, one or both players hit), but ensuring that this rule isn't easily deducible to the players. You could do this by making the rule a function of turn number (e.g. if both players press button 1 on turn #1 the output will be different to if they take the same action on turn #2).
I have an array (of 9 elements, say) which I must treat as a (3 by 3) square.
For the sake of simplifying the question, this is a one-based array (ie, indexing starts at 1 instead of 0).
My goal is to determine valid adjacent squares relative to a starting point.
In other words, how it's stored in memory: 1 2 3 4 5 6 7 8 9
How I'm treating it:
7 8 9
4 5 6
1 2 3
I already know how to move up and down and test for going out of bounds (1 >= current_index <= 9)
edit: I know the above test is overly general but it's simple and works.
//row_size = 3, row_step is -1, 0 or 1 depending on if we're going left,
//staying put or going right respectively.
current_index += (row_size * row_step);
How do I test for an out of bounds condition when going left or right? Conceptually I know it involves determining if 3 (for example) is on the same row as 4 (or if 10 is even within the same square as 9, as an alternate example, given that multiple squares are in the same array back to back), but I can't figure out how to determine that. I imagine there's a modulo in there somewhere, but where?
Thanks very much,
Geoff
Addendum:
Here's the resulting code, altered for use with a zero-based array (I cleaned up the offset code present in the project) which walks adjacent squares.
bool IsSameSquare(int index0, int index1, int square_size) {
//Assert for square_size != 0 here
return (!((index0 < 0) || (index1 < 0))
&& ((index0 < square_size) && (index1 < square_size)))
&& (index0 / square_size == index1 / square_size);
}
bool IsSameRow(int index0, int index1, int row_size) {
//Assert for row_size != 0 here
return IsSameSquare(index0, index1, row_size * row_size)
&& (index0 / row_size == index1 / row_size);
}
bool IsSameColumn(int index0, int index1, int row_size) {
//Assert for row_size != 0 here
return IsSameSquare(index0, index1, row_size * row_size)
&& (index0 % row_size == index1 % row_size);
}
//for all possible adjacent positions
for (int row_step = -1; row_step < 2; ++row_step) {
//move up, down or stay put.
int row_adjusted_position = original_position + (row_size * row_step);
if (!IsSameSquare(original_position, row_adjusted_position, square_size)) {
continue;
}
for (int column_step = -1; column_step < 2; ++column_step) {
if ((row_step == 0) & (column_step == 0)) { continue; }
//hold on to the position that has had its' row position adjusted.
int new_position = row_adjusted_position;
if (column_step != 0) {
//move left or right
int column_adjusted_position = new_position + column_step;
//if we've gone out of bounds again for the column.
if (IsSameRow(column_adjusted_position, new_position, row_size)) {
new_position = column_adjusted_position;
} else {
continue;
}
} //if (column_step != 0)
//if we get here we know it's safe, do something with new_position
//...
} //for each column_step
} //for each row_step
This is easier if you used 0-based indexing. These rules work if you subtract 1 from all your indexes:
Two indexes are in the same square if (a/9) == (b/9) and a >= 0 and b >= 0.
Two indexes are in the same row if they are in the same square and (a/3) == (b/3).
Two indexes are in the same column if they are in the same square and (a%3) == (b%3).
There are several way to do this, I'm choosing a weird one just for fun. Use modulus.
Ase your rows are size 3 just use modulus of 3 and two simple rules.
If currPos mod 3 = 0 and (currPos+move) mod 3 = 1 then invalid
If currPos mod 3 = 1 and (currPos+move) mod 3 = 0 then invalid
this check for you jumping two a new row, you could also do one rule like this
if (currPos mod 3)-((currPos+move) mod 3)> 1 then invalid
Cheers
You should be using a multidimensional array for this.
If your array class doesn't support multidimensional stuff, you should write up a quick wrapper that does.