Counting valleys question from hacker rank - python-3.x

Gary is an avid hiker. He tracks his hikes meticulously, paying close attention to small details like topography. During his last hike he took exactly steps. For every step he took, he noted if it was an uphill, , or a downhill, step. Gary's hikes start and end at sea level and each step up or down represents a unit change in altitude. We define the following terms:
A mountain is a sequence of consecutive steps above sea level, starting with a step up from sea level and ending with a step down to sea level.
A valley is a sequence of consecutive steps below sea level, starting with a step down from sea level and ending with a step up to sea level.
Given Gary's sequence of up and down steps during his last hike, find and print the number of valleys he walked through.
For example, if Gary's path is , he first enters a valley units deep. Then he climbs out an up onto a mountain units high. Finally, he returns to sea level and ends his hike.
Function Description
Complete the countingValleys function in the editor below. It must return an integer that denotes the number of valleys Gary traversed.
I have tried writing this code in python and it runs well but cannot figure out a code logically
#n is the number of steps and s is the sequence of steps taken
def countingValleys(n, s):
level=valley=0
for i in range(n):
if(s[i]=='U'):
level+=1
if(level==0):
valley+=1
else:
level-=1
return valley
Results are fine
Questions: Can someone explain me the logic starting from if(level==0). If we increase the level by one unit when the person moves uphill, shouldn't we increase valley by 1 then. Why should valley increase by one when level is zero. Confused about the logic- can someone please help me understand this

If the step is uphill if(s[i]=='U')
And the level is 0 if(level==0)
Then it is a valley valley+=1
The function works by counting the valleys when you come out of them, and it tells that you come out of them because you reach the sea level giving an uphill step.

Its simple,
What the code means is, if you have encountered an up symbol it means you have climbed. Now if you have climbed from plane or mountain your level would be greater than 0. But if you have climbed from a valley to level then only your level would become 0.
basically if level<0 it means you are still in valley, level>0 means you are in mountain, level 0 means you are in sea level.
So if you have encountered a up symbol denoting climb action and then your level is 0 that means you have climbed up a valley that's all.

We can assign values to uphill and downhill as uphill=1, downhill=-1 and sea level=0 and as valley can be defined as when we reached the sea level from downhill, i.e from a negative value to zero
so if we are at a negative level and moving to sea level by adding the next step we can increment the valley.
Find the code snippet below
def returnCode(step):
if step=='U':
return 1;
return -1;
def countingValleys(steps, path):
# Write your code here
level=valley=0
for element in path:
code = returnCode(element)
if level< 0 and level+code == 0:
valley=valley+1
level = level+code
return valley

Does
level=0 valley=0
make any difference, they both are similar level=valley=0
The logic is simple you just have to count if the no if "U"-uphill assigned as '1' and number of 'D'-Downhills assigned as '-1' and on adding the both count one should get '0' as in [DDDUUU] which will increment valley by '1'.

When level=0 Gary has reached sea level meaning he has covered a valley

In Javascript
function countingValleys(steps, path){
let altitude = 0;
let valleys = 0;
for(let i = 0; i < steps; i++){
altitude = (path[i] == 'U') ? altitude + 1 : altitude - 1;
if(altitude == 0 && path[i] == 'U'){
valleys++;
}
}
return valleys;
}
console.log(countingValleys(8, "UDDDUDUU"));

in php
function countingValleys($steps, $path) {
// Write your code here
$valley = 0;
$altitude = 0;
for($i=0; $i < $steps; $i++){
$altitude = ($path[$i] == "U") ? $altitude + 1 : $altitude -1;
if($altitude == 0 && $path[$i] == "U"){
$valley += 1;
}
}
return $valley;
}
countingValleys(8, "UDDDUDUU")

Solution in Golang
The function is expected to return an INTEGER.
The function accepts following parameters:
INTEGER steps
STRING path
*/
func countingValleys(steps int32, path string) int32 {
// Write your code here
//level 0 is sea
//level>0 is mountain
//level< 0 valley
// check the steps if its U do level+1
//if step is D do a level-1
level :=0
valley :=0
step := []rune(path)
for i:=0; i< int(steps);i++{
if string(step[i]) =="U"{
level= level+1
}else if string(step[i])=="D"{
level= level-1
}
if string(step[i])=="U" && level == 0{
valley++
}
}
return int32(valley)
}

Counting valley hacker solution in php
function countingValleys($steps, $path) {
$valley = 0;
$sealevel = 0;
$newPath = str_split($path);
$c = count($newPath);
if ($steps == $c && $c >= 2) {
for($i = 0; $i < $c; $i++) {
if ($newPath[$i] == "D") {
$sealevel -= 1;
} else {
$sealevel += 1;
}
if ($sealevel == 0 && $newPath[$i] == "U") {
$valley += 1;
}
}
return $valley;
}
}

Track the altitude. Any time you return back to sea-level and you came from below, you know you've found a valley. Keep count of these finding.
Time-complexity: O(steps)
Space-complexity: O(steps)
Java 8
public static int countingValleys(int steps, String path)
{
int altitude = 0; // 0 = sea-level
int countedValleys = 0;
//Loop through path evaluating each change in altitude
for(char altChange: path.toCharArray())
{
//'U' increases altitude. Otherwise, decrease altitude ('D')
altitude = altChange == 'U' ? altitude + 1 : altitude - 1;
//If you've reached sea-level and you came from below, you've found a valley
if(altitude == 0 && altChange == 'U')
countedValleys++;
}
//Return count of found valleys
return countedValleys;
}

Javascript Solution:
function countingValleys(steps, path) {
var altitude = 0;
var numberOfValleys = 0;
path.split('').forEach(step => {
if(step === 'U'){
altitude ++;
if(altitude === 0){
numberOfValleys++;
}
}else{
altitude--
}
})
return numberOfValleys;
}

#JavaScript(Nodejs) solution
function countingValleys(steps, path) {
// Write your code here
let a = Array.from(path);
let valleys=0;
let pos=0;
let prevpos=0;
for(let i=0;i<a.length;i++){
if(a[i]==='U'){
prevpos=pos++;
if(pos===0){
valleys++;
}
}
else
{
prevpos = pos--;
}
}
return valleys;
}

you can try this code with go
func countingValleys(steps int32, path string) int32 {
// Write your code here
var lv int;
var count int32;
var lembah bool;
for i := 0; i< int(steps); i++{
if path[i]== 'U' {lv ++;}else if path[i]== 'D'{lv--}
if lv<0 {lembah = true}
if lembah {
if(lv>=0){
count ++;
lembah = false;
}
}
}
return count;
}

Related

(DP) Memoization - How to know if it starts from the top or bottom?

It hasn't been long since I started studying algorithm coding tests, and I found it difficult to find regularity in Memoization.
Here are two problems.
Min Cost Climbing Stairs
You are given an integer array cost where cost[i] is the cost of ith step on a staircase. Once you pay the cost, you can either climb one or two steps.
You can either start from the step with index 0, or the step with index 1.
Return the minimum cost to reach the top of the floor.
Min Cost Climbing Stairs
Recurrence Relation Formula:
minimumCost(i) = min(cost[i - 1] + minimumCost(i - 1), cost[i - 2] + minimumCost(i - 2))
House Robber
You are a professional robber planning to rob houses along a street. Each house has a certain amount of money stashed, the only constraint stopping you from robbing each of them is that adjacent houses have security systems connected and it will automatically contact the police if two adjacent houses were broken into on the same night.
Given an integer array nums representing the amount of money of each house, return the maximum amount of money you can rob tonight without alerting the police.
House Robber
Recurrence Relation Formula:
robFrom(i) = max(robFrom(i + 1), robFrom(i + 2) + nums(i))
So as you can see, first problem consist of the previous, and second problem consist of the next.
Because of this, when I try to make recursion function, start numbers are different.
Start from n
int rec(int n, vector<int>& cost)
{
if(memo[n] == -1)
{
if(n <= 1)
{
memo[n] = 0;
} else
{
memo[n] = min(rec(n-1, cost) + cost[n-1], rec(n-2, cost) + cost[n-2]);
}
}
return memo[n];
}
int minCostClimbingStairs(vector<int>& cost) {
const int n = cost.size();
memo.assign(n+1,-1);
return rec(n, cost); // Start from n
}
Start from 0
int getrob(int n, vector<int>& nums)
{
if(how_much[n] == -1)
{
if(n >= nums.size())
{
return 0;
} else {
how_much[n] = max(getrob(n + 1, nums), getrob(n + 2, nums) + nums[n]);
}
}
return how_much[n];
}
int rob(vector<int>& nums) {
how_much.assign(nums.size() + 2, -1);
return getrob(0, nums); // Start from 0
}
How can I easily know which one need to be started from 0 or n? Is there some regularity?
Or should I just solve a lot of problems and increase my sense?
Your question is right, but somehow examples are not correct. Both the problems you shared can be done in both ways : 1. starting from top & 2. starting from bottom.
For example: Min Cost Climbing Stairs : solution that starts from 0.
int[] dp;
public int minCostClimbingStairs(int[] cost) {
int n = cost.length;
dp = new int[n];
for(int i=0; i<n; i++) {
dp[i] = -1;
}
rec(0, cost);
return Math.min(dp[0], dp[1]);
}
int rec(int in, int[] cost) {
if(in >= cost.length) {
return 0;
} else {
if(dp[in] == -1) {
dp[in] = cost[in] + Math.min(rec(in+1, cost), rec(in+2, cost));
}
return dp[in];
}
}
However, there are certain set of problems where this is not easy. Their structure is such that if you start in reverse, the computation could get complicated or mess up the future results:
Example: Reaching a target sum from numbers in an array using an index at max only 1 time. Reaching 10 in {3, 4, 6, 5, 2} : {4,6} is one answer but not {6, 2, 2} as you are using index (4) 2 times.
This can be done easily in top down way:
int m[M+10];
for(i=0; i<M+10; i++) m[i]=0;
m[0]=1;
for(i=0; i<n; i++)
for(j=M; j>=a[i]; j--)
m[j] |= m[j-a[i]];
If you try to implement in bottom up way, you will end up using a[i] multiple times. You can definitely do it bottom up way if you figure a out a way to tackle this messing up of states. Like using a queue to only store reached state in previous iterations and not use numbers reached in current iterations. Or even check if you keep a count in m[j] instead of just 1 and only use numbers where count is less than that of current iteration count. I think same thing should be valid for all DP.

How can I compare numbers when the language only has "loop while not zero"?

As a hobby project I have been developing an IDE for Chef, an esoteric programming language. While writing various test programs in Chef I've realised that implementing a simple sort algorithm, or even comparing two integers to see which one is greater, is a major challenge when the only compare-and-branch statement in the language is a loop which will repeat while a number is non zero. For example:
Dissolve the sugar. <-- execute loop if value of 'sugar' is non zero
Add flour to mixing bowl. <-- add value of 'flour' into mixing bowl
Set aside. <-- break out of the loop
Stir until dissolved. <-- mark the end of the loop
I do have a working solution to compare two integers in Chef, but it is 40 lines long!
Here is an equivalent of my approach in Java, which most will find more readable than the Chef code I wrote :-)
public static void main(String[] args) {
int first = 100;
int second = 200;
int looper = 1;
int tester;
int difference = first - second;
int inverse = difference * -1;
while (looper != 0) {
difference -= 1;
inverse -= 1;
tester = 1;
while (difference != 0) {
tester--;
break;
}
while (tester != 0) {
System.out.println("First is bigger");
exit(1);
}
tester = 1;
while (inverse != 0) {
tester--;
break;
}
while (tester != 0) {
System.out.println("Second is bigger");
exit(1);
}
}
}
My question is, what's the best way of comparing two numbers when all I have is a loop while non-zero ?

Iterative deepening search selected bad moves

I'm writing a Nine Men's Morris game and so far I have a Negascout search that works just fine. However, I would like to added iterative deepening, so I came up with this code:
public Move GetBestMove(IBoard board, int depth)
{
//Search limits (ms
this.maxTime = 9000;
//Set initial window
int alpha = -INFINITY, beta = INFINITY;
int val = 0;
//The move that will be returned
Move bestMove = null;
//Get list of moves for the current board
List<Move> moves = board.getMoves();
//Get the time search has started
long startTime = System.nanoTime();
//Iterate through the depths
for (curDepth = 1; ; )
{
maxDepth = curDepth;
//Reset alpha
alpha = -INFINITY;
//Reset the best score position
int bestPos = -1;
//Loop through all the moves
for (int i = 0, n = moves.size(); i < n; i++)
{
//Make the move
board.make(moves.get(i), true);
//Search deeper
val = negascout(board, curDepth, alpha, beta, startTime);
//Undo the move
board.undo(moves.get(i));
//Keep best move
if (val > alpha)
{
bestMove = moves.get(i);
bestPos = i;
}
//Score missed aspiration window
if (val <= alpha || val >= beta)
{
alpha = -INFINITY;
beta = INFINITY;
//Go to next iteration
continue;
}
//Set new aspiration window
alpha = val - ASPIRATION_SIZE;
if (alpha < -INFINITY)
alpha = -INFINITY;
beta = val + ASPIRATION_SIZE;
if (beta > INFINITY)
beta = INFINITY;
}
//Move the best move to the top of the list
if (bestPos != -1)
{
moves.remove(bestPos);
moves.add(0, bestMove);
}
//Time check
double curTime = (System.nanoTime() - startTime) / 1e6;
if (curTime >= maxTime ||
val == board.getMaxScoreValue() ||
val == -board.getMaxScoreValue())
break;
//Increment current depth
curDepth++;
}
//Return the move
return bestMove;
}
I also use an aspiration window. However, the search returns the worst possible move!! I think that the problem is with re-/setting the search window. Should the search window be moved to the outer loop?
Since you're using negascout, your initial call should look like
val = -negascout(board, curDepth - 1, -beta, -alpha, startTime);
Your root call is the exact opposite compared to internal nodes, so that explains why it's returning the worst possible move.
The iterative deepening strategy:
for (depth = 1;; depth++) {
val = AlphaBeta(depth, -INFINITY, INFINITY); // or negascout
if (TimedOut())
break;
}
looks different to the one you implemented with GetBestMove. The inner loop (iterating through the possible moves) should be part of negascout. Further it seems, that you only store the move ordering at first depth level (1-ply), but to make the iterative deepening search really fast, it needs a move ordering at every depth searched so far. Iterative deepening not only has the advantage to take time into account (finish after x seconds), but also has the advantage of generating a good move ordering. And the alphabeta or negascout algorithm benefits from a good move ordering (try this move first because in a previous search it was the best). A common way to get a move ordering implemented is the transposition table.
The documents The Main Transposition Table and Iterative Deepening from Bruce Moreland where very helpful to me and I hope that the links can help you too!

Google Interview : Find Crazy Distance Between Strings

This Question was asked to me at the Google interview. I could do it O(n*n) ... Can I do it in better time.
A string can be formed only by 1 and 0.
Definition:
X & Y are strings formed by 0 or 1
D(X,Y) = Remove the things common at the start from both X & Y. Then add the remaining lengths from both the strings.
For e.g.
D(1111, 1000) = Only First alphabet is common. So the remaining string is 111 & 000. Therefore the result length("111") & length("000") = 3 + 3 = 6
D(101, 1100) = Only First two alphabets are common. So the remaining string is 01 & 100. Therefore the result length("01") & length("100") = 2 + 3 = 5
It is pretty that obvious that do find out such a crazy distance is going to be linear. O(m).
Now the question is
given n input, say like
1111
1000
101
1100
Find out the maximum crazy distance possible.
n is the number of input strings.
m is the max length of any input string.
The solution of O(n2 * m) is pretty simple. Can it be done in a better way?
Let's assume that m is fixed. Can we do this in better than O(n^2) ?
Put the strings into a tree, where 0 means go left and 1 means go right. So for example
1111
1000
101
1100
would result in a tree like
Root
1
0 1
0 1* 0 1
0* 0* 1*
where the * means that an element ends there. Constructing this tree clearly takes O(n m).
Now we have to find the diameter of the tree (the longest path between two nodes, which is the same thing as the "crazy distance"). The optimized algorithm presented there hits each node in the tree once. There are at most min(n m, 2^m) such nodes.
So if n m < 2^m, then the the algorithm is O(n m).
If n m > 2^m (and we necessarily have repeated inputs), then the algorithm is still O(n m) from the first step.
This also works for strings with a general alphabet; for an alphabet with k letters build a k-ary tree, in which case the runtime is still O(n m) by the same reasoning, though it takes k times as much memory.
I think this is possible in O(nm) time by creating a binary tree where each bit in a string encodes the path (0 left, 1 right). Then finding the maximum distance between nodes of the tree which can be done in O(n) time.
This is my solution, I think it works:
Create a binary tree from all strings. The tree will be constructed in this way:
at every round, select a string and add it to the tree. so for your example, the tree will be:
<root>
<1> <empty>
<1> <0>
<1> <0> <1> <0>
<1> <0> <0>
So each path from root to a leaf will represent a string.
Now the distance between each two leaves is the distance between two strings. To find the crazy distance, you must find the diameter of this graph, that you can do it easily by dfs or bfs.
The total complexity of this algorithm is:
O(n*m) + O(n*m) = O(n*m).
I think this problem is something like "find prefix for two strings", you can use trie(http://en.wikipedia.org/wiki/Trie) to accerlate searching
I have a google phone interview 3 days before, but maybe I failed...
Best luck to you
To get an answer in O(nm) just iterate across the characters of all string (this is an O(n) operation). We will compare at most m characters, so this will be done O(m). This gives a total of O(nm). Here's a C++ solution:
int max_distance(char** strings, int numstrings, int &distance) {
distance = 0;
// loop O(n) for initialization
for (int i=0; i<numstrings; i++)
distance += strlen(strings[i]);
int max_prefix = 0;
bool done = false;
// loop max O(m)
while (!done) {
int c = -1;
// loop O(n)
for (int i=0; i<numstrings; i++) {
if (strings[i][max_prefix] == 0) {
done = true; // it is enough to reach the end of one string to be done
break;
}
int new_element = strings[i][max_prefix] - '0';
if (-1 == c)
c = new_element;
else {
if (c != new_element) {
done = true; // mismatch
break;
}
}
}
if (!done) {
max_prefix++;
distance -= numstrings;
}
}
return max_prefix;
}
void test_misc() {
char* strings[] = {
"10100",
"10101110",
"101011",
"101"
};
std::cout << std::endl;
int distance = 0;
std::cout << "max_prefix = " << max_distance(strings, sizeof(strings)/sizeof(strings[0]), distance) << std::endl;
}
Not sure why use trees when iteration gives you the same big O computational complexity without the code complexity. anyway here is my version of it in javascript O(mn)
var len = process.argv.length -2; // in node first 2 arguments are node and program file
var input = process.argv.splice(2);
var current;
var currentCount = 0;
var currentCharLoc = 0;
var totalCount = 0;
var totalComplete = 0;
var same = true;
while ( totalComplete < len ) {
current = null;
currentCount = 0;
for ( var loc = 0 ; loc < len ; loc++) {
if ( input[loc].length === currentCharLoc) {
totalComplete++;
same = false;
} else if (input[loc].length > currentCharLoc) {
currentCount++;
if (same) {
if ( current === null ) {
current = input[loc][currentCharLoc];
} else {
if (current !== input[loc][currentCharLoc]) {
same = false;
}
}
}
}
}
if (!same) {
totalCount += currentCount;
}
currentCharLoc++;
}
console.log(totalCount);

Is it possible to do a Levenshtein distance in Excel without having to resort to Macros?

Let me explain.
I have to do some fuzzy matching for a company, so ATM I use a levenshtein distance calculator, and then calculate the percentage of similarity between the two terms. If the terms are more than 80% similar, Fuzzymatch returns "TRUE".
My problem is that I'm on an internship, and leaving soon. The people who will continue doing this do not know how to use excel with macros, and want me to implement what I did as best I can.
So my question is : however inefficient the function may be, is there ANY way to make a standard function in Excel that will calculate what I did before, without resorting to macros ?
Thanks.
If you came about this googling something like
levenshtein distance google sheets
I threw this together, with the code comment from milot-midia on this gist (https://gist.github.com/andrei-m/982927 - code under MIT license)
From Sheets in the header menu, Tools -> Script Editor
Name the project
The name of the function (not the project) will let you use the func
Paste the following code
function Levenshtein(a, b) {
if(a.length == 0) return b.length;
if(b.length == 0) return a.length;
// swap to save some memory O(min(a,b)) instead of O(a)
if(a.length > b.length) {
var tmp = a;
a = b;
b = tmp;
}
var row = [];
// init the row
for(var i = 0; i <= a.length; i++){
row[i] = i;
}
// fill in the rest
for(var i = 1; i <= b.length; i++){
var prev = i;
for(var j = 1; j <= a.length; j++){
var val;
if(b.charAt(i-1) == a.charAt(j-1)){
val = row[j-1]; // match
} else {
val = Math.min(row[j-1] + 1, // substitution
prev + 1, // insertion
row[j] + 1); // deletion
}
row[j - 1] = prev;
prev = val;
}
row[a.length] = prev;
}
return row[a.length];
}
You should be able to run it from a spreadsheet with
=Levenshtein(cell_1,cell_2)
While it can't be done in a single formula for any reasonably-sized strings, you can use formulas alone to compute the Levenshtein Distance between strings using a worksheet.
Here is an example that can handle strings up to 15 characters, it could be easily expanded for more:
https://docs.google.com/spreadsheet/ccc?key=0AkZy12yffb5YdFNybkNJaE5hTG9VYkNpdW5ZOWowSFE&usp=sharing
This isn't practical for anything other than ad-hoc comparisons, but it does do a decent job of showing how the algorithm works.
looking at the previous answers to calculating Levenshtein distance, I think it would be impossible to create it as a formula.
Take a look at the code here
Actually, I think I just found a workaround. I was adding it in the wrong part of the code...
Adding this line
} else if(b.charAt(i-1)==a.charAt(j) && b.charAt(i)==a.charAt(j-1)){
val = row[j-1]-0.33; //transposition
so it now reads
if(b.charAt(i-1) == a.charAt(j-1)){
val = row[j-1]; // match
} else if(b.charAt(i-1)==a.charAt(j) && b.charAt(i)==a.charAt(j-1)){
val = row[j-1]-0.33; //transposition
} else {
val = Math.min(row[j-1] + 1, // substitution
prev + 1, // insertion
row[j] + 1); // deletion
}
Seems to fix the problem. Now 'biulding' is 92% accurate and 'bilding' is 88%. (whereas with the original formula 'biulding' was only 75%... despite being closer to the correct spelling of building)

Resources