Find Maximun area on Array - arrays

I am doing exercises from the app Data Structures in Scala, I have coded the second problem on Arrays like this:
/**
* Given n non-negative integers a1, a2, ..., an, where each represents a
* point at coordinate (i, ai), n vertical lines are drawn such that
* the two endpoints of line i is at (i, ai) and (i, 0).
*
* Find two lines, which together with x-axis forms a container such
* that the container contains the most water.
*
* Efficiency: O(n)
*
* #param a Array of line heights
* #return Maximum area
*/
def maxArea(a: Array[Int]): Int = {
#tailrec
def go(l: Int, r: Int)(max: Int): Int = {
if (l >= r) max
else {
val currArea = math.min(a(l), a(r)) * (r - l)
val area = math.max(max, currArea)
log debug s"Current area for $l and $r is $currArea"
log debug s"Max area till now is $area"
if (a(l) < a(r)) go(l + 1, r)(area)
else go(l, r - 1)(area)
}
}
go(0, a.size - 1)(0)
}
I wonder if there is a better alternative to write recursive functions as a way of looping through the Array, as someone once told me calls recursion the GOTO of functional programming.
You can check the complete source code at GitHub
Thank you in advance.

Here's a way to implement your algorithm without recursion (not that I actually think there's anything inherently wrong with recursion).
def maxArea2(a: Array[Int]): Int = {
Stream.iterate(0 -> a){ case (_, arr) =>
if (arr.length < 2) -1 -> arr
else {
val (lft, rght) = (arr.head, arr.last)
val area = (lft min rght) * (arr.length - 1)
if (lft <= rght) area -> arr.dropWhile(_ <= lft)
else area -> arr.reverse.dropWhile(_ <= rght)
}
}.takeWhile(_._1 >= 0).maxBy(_._1)._1
}
The idea is to iterate lazily and the take (i.e. realize) only those you need.
You'll note that this iterates, and calculates areas, fewer times because it drops values that can't beat the current area calculation.

Related

How to create matrix in matlab that adds cells horizontally

I want to create a matrix, for example, a 1xn, where n is determined by another input.
For example, I have the following:
Example = [3 5 7 9];
New_matrix = [int_col(Example (1)) int_col(Example (2)) int_col(Example (3)) int_col(Example (4))];
This New_matrix is how I want my outputs.
However, for my actual data input, my Example matrix is 1x47. How can I put this in a for loop so it gives the outputs of 1 to a specified number for all of the length Example? (keeping it horizontal as well)
Help function I used is added here:
% Helper function added as well
function v = int_col(n)
v = zeros(1,n);
for index=1:n
val = randi(n);
while (val == index || any(val == v))
val = randi(n);
if (index == n && (any(v == n) ~= 1))
val = n;
break
end
end
v(index) = val;
if (index == n && val == n)
% v(n) = v(n-1);
% v(n-1) = n;
end
if n == 1
v = 1;
end
end
v = v';
v = (sortrows(v))';
end
Are you trying to reimplement randperm() in int_col()? I'm not sure what the purpose of running sortrows() on each column separately is, but I guess this may be what you wanted:
% Make up vector of column lengths
Example=randi(60,[1 47]);
% Create matrix
New_matrix=nan([max(Example) numel(Example)]);
for i=1:numel(Example)
New_matrix(1:Example(i),i)=randperm(Example(i));
end
% Sort matrix rows from left to right
New_matrix=sortrows(New_matrix);
Please note that all columns in a matrix must have the same number of entries, so you will need to pad shorter columns with some value; a typical choice is NaN, which is treated as a special value by sortrows() and some other functions.
~
If my guess is incorrect and you do mean your code as it currently is, you just need:
New_matrix=[];
for i=1:numel(Example)
New_matrix=[New_matrix 1:Example(i)];
end
Changing the size of New_matrix on every iteration is generally not good practice, but for 47 iterations only this should be fine.

Finding permutations of Array without for loops

I saw this interview question on a LinkedIn group here
To summarise, if I have an array
[1,2,3,4,5]
and input
3
I require the output
[1,2,3], [3,2,1], [2,3,1], [2,1,3], [1,3,2], [3,1,2], [2,3,4], [4,3,2],...
In no particular order.
I have been thinking about this one for a while now. I have come up with various different ways of solving but all methods use for-loops.
I think it's clear that in order to eliminate loops it must be recursive.
I thought I got close to doing this recursively partitioning the array and joining elements, but with great frustration I ended up requiring another for loop.
Im beginning to think this is impossible (which it can't be, otherwise why the interview question?).
Any ideas or links? The amount of possible outputs should be 5PN, where N is the input.
The following recursive algorithm will attempt to print every subset of {1,.., n}. These subsets are in one to one with numbers between 0 and 2^n-1 via the following bijection: to an integer x between 0 and 2^n-1, associate the set that contains 1 if the first bit of x is set to one, 2 if the second bit of x is set to one, ..
void print_all_subsets (int n, int m, int x) {
if (x==pow(2,n)) {
return;
}
else if (x has m bits set to one) {
print the set corresponding to x;
}
print_all_subsets(n,m,x+1);
}
You need to call it with n = 5 (in your case), m=3 (in your case), and x = 0.
Then you need to implement the two functions "print the set corresponding to x" and "x has m bits set to one" without for loops... but this is easily done using again recursion.
However, I think this is more of a challenge -- there is no point in completely eliminating for-loops, what makes sense is just to use them in a smart way.
Your first thought is right. Every loop can be replaced with recursion. In some languages (for example Scheme), loops are actually implemented with recursion. So just start with any solution, and keep on turning loops into recursion. Eventually you will be done.
Here is a working solution in Python.
def subsets_of_size (array, size, start=0, prepend=None):
if prepend is None:
prepend = [] # Standard Python precaution with modifiable defaults.
if 0 == size:
return [[] + prepend] # Array with one thing. The + forces a copy.
elif len(array) < start + size:
return [] # Array with no things.
else:
answer = subsets_of_size(array, size, start=start + 1, prepend=prepend)
prepend.append(array[start])
answer = answer + subsets_of_size(array, size-1, start=start + 1, prepend=prepend)
prepend.pop()
return answer
print subsets_of_size([1,2,3,4,5], 3)
I don't think the solution is not to use for-loop but there is an optimum way to use for-loop.
And so, there is the Heap's Algorithm. Below from wiki http://en.wikipedia.org/wiki/Heap%27s_algorithm
procedure generate(n : integer, A : array of any):
if n = 1 then
output(A)
else
for i := 0; i < n; i += 1 do
generate(n - 1, A)
if n is even then
swap(A[i], A[n - 1])
else
swap(A[0], A[n-1])
end if
end for
end if
define listPermutations:
input: int p_l , int[] prevP , int atElement , int[] val , int nextElement
output: list
if nextElement > length(val) OR atElement == p_l OR contains(prevP , val[nextElement]
return EMPTY
list result
int[] tmp = copy(prevP)
tmp[atElement] = val[nextElement]
add(result , tmp)
//create the next permutation stub with the last sign different to this sign
//(node with the same parent)
addAll(result , listPermutations(p_l , tmp , atElement , val , nextElement + 1))
//create the next permutation stub with an additional sign
//(child node of the current permutation
addAll(result , listPermutations(p_l , tmp , atElement + 1 , val , 0))
return result
//this will return the permutations for your example input:
listPermutations(3 , new int[3] , 0 , int[]{1 , 2 , 3 , 4 , 5} , 0)
Basic idea: all permutations of a given number of elements form a tree, where the node is the empty permutation and all childnodes of a node have one additional element. Now all the algorithm has to do is to traverse this tree level by level, until the level is equal to the required length of the permutation and list all nodes on that level
You could use recursion here, and every time you call an inner level, you give it the location it is in the array and when it returns it return an increased location. You'd be using one while loop for this.
Pseudo code:
int[] input = [1,2,3,4,5];
int level = 3;
int PrintArrayPermutation(int level, int location, string base)
{
if (level == 0)
{
print base + input[location];
return location + 1;
}
while (location <= input.Length)
{
location =
PrintArrayPermutation(level - 1, location, base + input[location]);
}
}
This is a very basic outline of my idea.
Here are two recursive functions in JavaScript. The first is the combinatorial choose function to which we apply the second function, permuting each result (permutator is adapted from the SO user, delimited's, answer here: Permutations in JavaScript?)
function c(n,list){
var result = [];
function _c(p,r){
if (p > list.length)
return
if (r.length == n){
result = result.concat(permutator(r));
} else {
var next = list[p],
_r = r.slice();
_r.push(next)
_c(p+1,_r);
_c(p+1,r);
}
}
_c(0,[])
return result;
}
function permutator(inputArr) {
var results = [];
function permute(arr, memo) {
var cur, memo = memo || [];
function _permute (i,arr,l){
if (i == l)
return
cur = arr.splice(i,1);
if (arr.length === 0){
results.push(memo.concat(cur));
}
permute(arr.slice(), memo.concat(cur));
arr.splice(i, 0, cur[0]);
_permute(i + 1,arr,l)
}
_permute(0,arr,arr.length);
return results;
}
return permute(inputArr);
}
Output:
console.log(c(3,[1,2,3,4,5]))
[[1,2,3],[1,3,2],[2,1,3]...[4,5,3],[5,3,4],[5,4,3]]

Incrementing Variable in a foldLeft

I have Scala code like this
var i = 1
for(e <- array) {
acc += e * i
i += 1
}
I need to multiply the first element in the array by 1, the next by 2, the next by 3 and so on adding it all into an accumulator. I feel that there is a better way of doing this in Scala, maybe even with folding?
"Better" depends on what your goals are. Short and clear? Probably
{ for (i <- array.indices; e = array(i)) yield (i+1)*e }.sum
or
array.indices.map(i => (i+1)*array(i)).sum
(or slightly faster, since you create the intermediates as you go:
array.indices.iterator.map(i => (i+1)*array(i)).sum
).
You should usually be short and clear.
Fast? Then you'll need to go old-school:
var i = 0
var acc = 0
while (i < array.length) {
acc += (i+1)*array(i)
i += 1
}
or use recursion
def sum(a: Array[Int], i: Int = 0, acc: Int = 0): Int =
if (i >= a.length) acc else sum(a, i+1, (i+1)*a(i) + acc)
sum(array)
I prefer zipWithIndex which is simpler to read:
array.zipWithIndex.map { case (e, i) => e * (i + 1) }.sum
val x = List(1,1,1,1,1,1)
(((0,1) /: x){case ((acc, mult), l) => (acc + (l * mult), mult + 1) })._1
In other words, starting with an accumulator of 0 and a multiplier of 1, fold each element of the list in, changing the accumulator to acc + (l * mult) and incrementing the multiplier by 1. We get the final multiplier out at the end as well, so we call ._1 to just get the accumulator.
Edit: As #RexKerr points in his answer below (and the comment), if performance is a major concern then you're better off using an explicit recursive method.
I am not sure if what I suggest is a better way to do it or not, as it is more functional (== it will perform slower):
(0 /: (array zipWithIndex)) {(a, i) => (i._1 * (i._2 + 1)) + a}
This does perform foldLeft on an array which is produced by zipWithIndex method in http://www.scala-lang.org/api/current/index.html#scala.Array
zipWithIndex simply zips the elements of a collection with their indices.

Finding contiguous ranges in arrays

You are given an array of integers. You have to output the largest range so that all numbers in the range are present in the array. The numbers might be present in any order. For example, suppose that the array is
{2, 10, 3, 12, 5, 4, 11, 8, 7, 6, 15}
Here we find two (nontrivial) ranges for which all the integers in these ranges are present in the array, namely [2,8] and [10,12]. Out of these [2,8] is the longer one. So we need to output that.
When I was given this question, I was asked to do this in linear time and without using any sorting. I thought that there might be a hash-based solution, but I couldn't come up with anything.
Here's my attempt at a solution:
void printRange(int arr[])
{
int n=sizeof(arr)/sizeof(int);
int size=2;
int tempans[2];
int answer[2];// the range is stored in another array
for(int i =0;i<n;i++)
{
if(arr[0]<arr[1])
{
answer[0]=arr[0];
answer[1]=arr[1];
}
if(arr[1]<arr[0])
{
answer[0]=arr[1];
answer[1]=arr[0];
}
if(arr[i] < answer[1])
size += 1;
else if(arr[i]>answer[1]) {
initialize tempans to new range;
size2=2;
}
else {
initialize tempans to new range
}
}
//I have to check when the count becomes equal to the diff of the range
I am stuck at this part... I can't figure out how many tempanswer[] arrays should be used.
I think that the following solution will work in O(n) time using O(n) space.
Begin by putting all of the entries in the array into a hash table. Next, create a second hash table which stores elements that we have "visited," which is initially empty.
Now, iterate across the array of elements one at a time. For each element, check if the element is in the visited set. If so, skip it. Otherwise, count up from that element upward. At each step, check if the current number is in the main hash table. If so, continue onward and mark the current value as part of the visited set. If not, stop. Next, repeat this procedure, except counting downward. This tells us the number of contiguous elements in the range containing this particular array value. If we keep track of the largest range found this way, we will have a solution to our problem.
The runtime complexity of this algorithm is O(n). To see this, note that we can build the hash table in the first step in O(n) time. Next, when we begin scanning to array to find the largest range, each range scanned takes time proportional to the length of that range. Since the total sum of the lengths of the ranges is the number of elements in the original array, and since we never scan the same range twice (because we mark each number that we visit), this second step takes O(n) time as well, for a net runtime of O(n).
EDIT: If you're curious, I have a Java implementation of this algorithm, along with a much more detailed analysis of why it works and why it has the correct runtime. It also explores a few edge cases that aren't apparent in the initial description of the algorithm (for example, how to handle integer overflow).
Hope this helps!
The solution could use BitSet:
public static void detect(int []ns) {
BitSet bs = new BitSet();
for (int i = 0; i < ns.length; i++) {
bs.set(ns[i]);
}
int begin = 0;
int setpos = -1;
while((setpos = bs.nextSetBit(begin)) >= 0) {
begin = bs.nextClearBit(setpos);
System.out.print("[" + setpos + " , " + (begin - 1) + "]");
}
}
Sample I/O:
detect(new int[] {2,10, 3, 12, 5,4, 11, 8, 7, 6, 15} );
[2,8] [10,12] [15,15]
Here is the solution in Java:
public class Solution {
public int longestConsecutive(int[] num) {
int longest = 0;
Map<Integer, Boolean> map = new HashMap<Integer, Boolean>();
for(int i = 0; i< num.length; i++){
map.put(num[i], false);
}
int l, k;
for(int i = 0;i < num.length;i++){
if(map.containsKey(num[i]-1) || map.get(num[i])) continue;
map.put(num[i], true);
l = 0; k = num[i];
while (map.containsKey(k)){
l++;
k++;
}
if(longest < l) longest = l;
}
return longest;
}
}
Other approaches here.
The above answer by template will work but you don't need a hash table. Hashing could take a long time depending on what algorithm you use. You can ask the interviewer if there's a max number the integer can be, then create an array of that size. Call it exist[] Then scan through arr and mark exist[i] = 1; Then iterate through exist[] keeping track of 4 variables, size of current largest range, and the beginning of the current largest range, size of current range, and beginning of current range. When you see exist[i] = 0, compare the current range values vs largest range values and update the largest range values if needed.
If there's no max value then you might have to go with the hashing method.
Actually considering that we're only sorting integers and therefore a comparision sort is NOT necessary, you can just sort the array using a Radix- or BucketSort and then iterate through it.
Simple and certainly not what the interviewee wanted to hear, but correct nonetheless ;)
A Haskell implementation of Grigor Gevorgyan's solution, from another who didn't get a chance to post before the question was marked as a duplicate...(simply updates the hash and the longest range so far, while traversing the list)
import qualified Data.HashTable.IO as H
import Control.Monad.Random
f list = do
h <- H.new :: IO (H.BasicHashTable Int Int)
g list (0,[]) h where
g [] best h = return best
g (x:xs) best h = do
m <- H.lookup h x
case m of
Just _ -> g xs best h
otherwise -> do
(xValue,newRange) <- test
H.insert h x xValue
g xs (maximum [best,newRange]) h
where
test = do
m1 <- H.lookup h (x-1)
m2 <- H.lookup h (x+1)
case m1 of
Just x1 -> case m2 of
Just x2 -> do H.insert h (x-1) x2
H.insert h (x+1) x1
return (x,(x2 - x1 + 1,[x1,x2]))
Nothing -> do H.insert h (x-1) x
return (x1,(x - x1 + 1,[x,x1]))
Nothing -> case m2 of
Just x2 -> do H.insert h (x+1) x
return (x2,(x2 - x + 1,[x,x2]))
Nothing -> do return (x,(1,[x]))
rnd :: (RandomGen g) => Rand g Int
rnd = getRandomR (-100,100)
main = do
values <- evalRandIO (sequence (replicate (1000000) rnd))
f values >>= print
Output:
*Main> main
(10,[40,49])
(5.30 secs, 1132898932 bytes)
I read a lot of solutions on multiple platforms to this problem and one got my attention, as it solves the problem very elegantly and it is easy to follow.
The backbone of this method is to create a set/hash which takes O(n) time and from there every access to the set/hash will be O(1). As the O-Notation omit's constant terms, this Algorithm still can be described overall as O(n)
def longestConsecutive(self, nums):
nums = set(nums) # Create Hash O(1)
best = 0
for x in nums:
if x - 1 not in nums: # Optimization
y = x + 1 # Get possible next number
while y in nums: # If the next number is in set/hash
y += 1 # keep counting
best = max(best, y - x) # counting done, update best
return best
It's straight forward if you ran over it with simple numbers. The Optimization step is just a short-circuit to make sure you start counting, when that specific number is the beginning of a sequence.
All Credits to Stefan Pochmann.
Very short solution using Javascript sparse array feature:
O(n) time using O(n) additional space.
var arr = [2, 10, 3, 12, 5, 4, 11, 8, 7, 6, 15];
var a = [];
var count = 0, max_count = 0;
for (var i=0; i < arr.length; i++) a[arr[i]] = true;
for (i = 0; i < a.length; i++) {
count = (a[i]) ? count + 1 : 0;
max_count = Math.max(max_count, count);
}
console.log(max_count); // 7
A quick way to do it (PHP) :
$tab = array(14,12,1,5,7,3,4,10,11,8);
asort($tab);
$tab = array_values($tab);
$tab_contiguous = array();
$i=0;
foreach ($tab as $key => $val) {
$tab_contiguous[$i][] = $tab[$key];
if (isset($tab[$key+1])) {
if($tab[$key] + 1 != $tab[$key+1])
$i++;
}
}
echo(json_encode($tab_contiguous));

How would one write down this mathematical expression programmatically?

The sum of f(i) for all integers i =
k, k + 1, .., continuing only as long
as the condition p(i) holds.
I'm going for:
for (i = 0; i <= V_COUNT; i++) {
sum += sine_coeff[i] * pow(E, e_factor[i]) * sin(
(solar_coeff[i] * solar_anomaly)
+ (lunar_coeff[i] * lunar_anomaly)
+ (moon_coeff[i] * moon_argument)
);
}
based on the following Common LISP code:
(sigma ((v sine-coeff)
(w E-factor)
(x solar-coeff)
(y lunar-coeff)
(z moon-coeff))
(* v (expt cap-E w)
(sin-degrees
(+ (* x solar-anomaly)
(* y lunar-anomaly)
(* z moon-argument)))))))
where sigma is:
(defmacro sigma (list body)
;; TYPE (list-of-pairs (list-of-reals->real))
;; TYPE -> real
;; $list$ is of the form ((i1 l1)..(in ln)).
;; Sum of $body$ for indices i1..in
;; running simultaneously thru lists l1..ln.
`(apply '+ (mapcar (function (lambda
,(mapcar 'car list)
,body))
,#(mapcar 'cadr list))))
(for full source code, see Calendrical calculations source code
Edit
Thanks for all your answers. Investigating the code examples, I have come to the conclusion that, in programming terms, the author indeed ment that one has to loop over a certain set of values. From that, it was easy to conclude that p had to return False when it has run out of values, i.e. control has reached the end of the list.
Define a function p(), e.g.:
bool_t p(int i)
{
// some conditional code here, that returns TRUE or FALSE
}
It seems like you need to loop for an arbitrarily long time (i.e. there's no hard upper limit), and you need to stop looping when p(i) returns FALSE. Therefore, you probably want a loop something like this:
int sum = 0;
for (int i = k; p(i); i++)
{
sum += f(i);
}
Depending on how large i and sum can get, you may want to declare them as long rather than int.
Something like:
sum = 0;
i = k;
while (p(i))
sum += f(i++);

Resources