'if' scenario in an equation. How do I implement it? - numerical

Basically I've been trying to make a working hours calculator and I've run into a problem. When the start time's value is greater than the finish time (eg. start is 23 and finish is 19), the result comes up as a negative. So what I want it to do in that scenario is to then multiply the negative number by -1 to make it positive again. However, this code below doesn't seem to have any effect in my app.
-(IBAction)done:(id)sender {
int result = [finishHours.text intValue] - [startHours.text intValue];
totalHours.text = [NSString stringWithFormat:#"%i", result];
if (result < 0) {
result = result * -1;
}

You set totalHours.text before you change the sign of your result variable.

what do you mean it doesn't have any effect? is it because you have changed result after you have set totalHours? would this fix your issue?
-(IBAction)done:(id)sender {
int result = [finishHours.text intValue] - [startHours.text intValue];
if (result < 0) {
result = result * -1;
}
totalHours.text = [NSString stringWithFormat:#"%i", result];

Related

How to find two optimal weights in a vector?

Imagine you're given an unsorted array [5,11,7,4,19,8,11,6,17] and a max weight 23. [similar to Two Sum Problem by a bit different]
One needs to find two optimal weights (by which I mean if two weights that are (almost or not) half of the weight you're trying to find) in this case [5,17], [3,19], [11,11] so I need to return [11,11].
I was taken back by the problem, and could not solve it. [I was not allowed to use structs]
I tried to sort [3, 5, 6, 7, 8, 11, 11, 17, 19] and search from both ends and store indexes of values that were <= max weight in a vector as a pair (like v[i], v[i+1] and check them later by their pairs) then return a pair with both largest vals, but got confused.
[although, weights were doubles and I did not see duplicates at that set I did not use unsorted_map(hashMap), might it've worked?]
Can anyone suggest how should I go about this problem? is it similar to "knapsack problem"? Thank you
You can use Two Pointer Approach for the problem.
Algorithm:
Sort the array.
Have two pointers startIndex and endIndex to 0 and arraySize-1.
sum = arr[startIndex] + arr[endIndex]
If sum is less than or equal to 23, increment startIndex else decrement endIndex.
keep track of closest value using a variable.
finish when startIndex == endIndex
Code in Java:
public class Solution {
private ArrayList<Integer> twoSumClosest(ArrayList<Integer> a, int s) {
// Sort the arraylist
Collections.sort(a);
// closests sum we got till now
int sumClosest = Integer.MIN_VALUE;
// indexes used to traverse
int startIndex = 0;
int endIndex = a.size() - 1 ;
// answer Indexes
int firstIndex = 1;
int secondIndex = a.size() - 1;
while( startIndex < endIndex ) {
if( a.get(startIndex) + a.get(endIndex) > s) {
endIndex--;
continue;
} else {
if( a.get(startIndex) + a.get(endIndex) > sumClosest ) {
sumClosest = a.get(startIndex) + a.get(endIndex);
firstIndex = startIndex;
secondIndex = endIndex;
}
startIndex++;
}
}
ArrayList<Integer> ans = new ArrayList<>();
ans.add(firstIndex);
ans.add(secondIndex);
return ans;
}
}
Time Complexity: O(nlogn)
O(n) if array was already sorted
Extra Space Needed: O(1)

Why is this recursive function exceeding call stack size?

I'm trying to write a function to find the lowest number that all integers between 1 and 20 divide. (Let's call this Condition D)
Here's my solution, which is somehow exceeding the call stack size limit.
function findSmallest(num){
var count = 2
while (count<21){
count++
if (num % count !== 0){
// exit the loop
return findSmallest(num++)
}
}
return num
}
console.log(findSmallest(20))
Somewhere my reasoning on this is faulty but here's how I see it (please correct me where I'm wrong):
Calling this function with a number N that doesn't meet Condition D will result in the function being called again with N + 1. Eventually, when it reaches a number M that should satisfy Condition D, the while loop runs all the way through and the number M is returned by the function and there are no more recursive calls.
But I get this error on running it:
function findSmallest(num){
^
RangeError: Maximum call stack size exceeded
I know errors like this are almost always due to recursive functions not reaching a base case. Is this the problem here, and if so, where's the problem?
I found two bugs.
in your while loop, the value of count is 3 to 21.
the value of num is changed in loop. num++ should be num + 1
However, even if these bugs are fixed, the error will not be solved.
The answer is 232792560.
This recursion depth is too large, so stack memory exhausted.
For example, this code causes same error.
function foo (num) {
if (num === 0) return
else foo(num - 1)
}
foo(232792560)
Coding without recursion can avoid errors.
Your problem is that you enter the recursion more than 200 million times (plus the bug spotted in the previous answer). The number you are looking for is the multiple of all prime numbers times their max occurrences in each number of the defined range. So here is your solution:
function findSmallestDivisible(n) {
if(n < 2 || n > 100) {
throw "Numbers between 2 and 100 please";
}
var arr = new Array(n), res = 2;
arr[0] = 1;
arr[1] = 2;
for(var i = 2; i < arr.length; i++) {
arr[i] = fix(i, arr);
res *= arr[i];
}
return res;
}
function fix(idx, arr) {
var res = idx + 1;
for(var i = 1; i < idx; i++) {
if((res % arr[i]) == 0) {
res /= arr[i];
}
}
return res;
}
https://jsfiddle.net/7ewkeamL/

Recursive Merge Sort Without Arrays

This is a problem I'm working on right now without any idea how to solve. I'm supposed to write the pseudocode to the merge function, but I'm not sure what I'm supposed to do. What I've been given is as follows:
Begin MergeSort(L[], start, stop)
if (stop<=start) return;
int m = (start+stop)/2;
MergeSort(L, start, m);
Mergesort(L, m+1, stop);
merge(L, start, m, stop);
End MergeSort
The only other thing I've been told is that I'm supposed to find the "merge(L, start, m, stop);" line. I've been researching all day, and everything I've found says that you should have 2 arrays, called left and right, to assign the recursive lines, making:
Begin MergeSort(L[], start, stop)
if (stop<=start) return;
array left[];
array right[];
int m = (start+stop)/2;
left=MergeSort(L, start, m);
right=Mergesort(L, m+1, stop);
merge(L, start, m, stop);
End MergeSort
If I were given this problem, I would be able to solve it, but I'm stuck because once I've broken each sublist into single elements, I'm not even sure what I'm supposed to call them, so I'm not sure how to work with them.
I'm still a beginner when it comes to code (taking the very basics of C and Python), so please keep the answer simple, if possible.
Thank you very much for reading this, and I hope that I get an answer so I understand what I'm doing.
MergeSort consists of 2 functions: mergeSort and merge. First one you have already written correctly. So, the only you problem with merge function.
Because of merge sort is not in-space sort algorithm, it require extra space to store data. Bellow is pretty simplified version of merge function that creates extra array of size stop - start:
Begin merge(L[] array, int start, int m, int stop)
if (start == stop) {
return;
}
int leftPos = start;
int rightPos = m + 1;
int curPos = start;
L[] temp = new L[stop - start];
while(leftPos <= m && rightPos <= stop) {
if (array[leftPos] <= array[rightPos]) {
temp[curPos++] = array[leftPos++];
} else {
temp[curPos++] = array[rightPos++];
}
}
while(leftPos <= m) {
temp[curPos++] = array[leftPos++];
}
while(rightPos <= stop) {
temp[curPos++] = array[rightPos++];
}
for (int i = start; i <= stop; i++) {
array[i] = temp[i - start];
}
End merge

Regarding IndexOutOfRange error asp.net c#

Hi
i am creating online quiz. For that i am creating arrays of answers selected by user. i used following code for that, it gives correct array but sometimes gives error "Index was outside the range"
//rsel is session values for selected answer
int rsel = Convert.ToInt32(Session["rblsel"]);
// [Convert.ToInt32(Session["Counter"] indicates size of array of no. of questions
int[] ansarray = new int[Convert.ToInt32(Session["Counter"]) - 1];
int[] temp = (int[])Session["arrofans"];
int j,n;
if (temp == null)
n = 0;
else
n = temp.Length;
for (j = 0; j < n; j++)
{
ansarray[j] = temp[j];
}
ansarray[j] = rsel;
Session["arrofans"] = ansarray;
Help me to find out exact error. Asp.net,c#
Thank you.
Why are you reducing the "counter" by one?
int[] ansarray = new int[Convert.ToInt32(Session["Counter"]) - 1];
It looks like that should probably be a + 1... but to be honest it would be simpler to use the size of ansarray - and use Array.Resize to effectively extend it:
int[] ansarray = (int[])Session["arrofans"];
Array.Resize(ref ansarray, ansarray.Length + 1);
ansarray[ansarray.Length - 1] = rsel;
Session["arrofans"] = ansarray;
That way you don't even need the "Counter" part of the session.
One possible OutOfRange could be triggered when
**arrofans.length >= Counter**
temp.Length should not be bigger than ansarray.Length, or precisely from your code it ansarray.Length must be temp.Length+1 or bigger. To avoid your problem you must change it to for (j = 0; j < n && j < (ansarray.Length-1); j++) but i don't know if it will suite your case

Handling large groups of numbers

Project Euler problem 14:
The following iterative sequence is
defined for the set of positive
integers:
n → n/2 (n is even) n → 3n + 1 (n is
odd)
Using the rule above and starting with
13, we generate the following
sequence: 13 → 40 → 20 → 10 → 5 → 16 →
8 → 4 → 2 → 1
It can be seen that this sequence
(starting at 13 and finishing at 1)
contains 10 terms. Although it has not
been proved yet (Collatz Problem), it
is thought that all starting numbers
finish at 1.
Which starting number, under one
million, produces the longest chain?
My first instinct is to create a function to calculate the chains, and run it with every number between 1 and 1 million. Obviously, that takes a long time. Way longer than solving this should take, according to Project Euler's "About" page. I've found several problems on Project Euler that involve large groups of numbers that a program running for hours didn't finish. Clearly, I'm doing something wrong.
How can I handle large groups of numbers quickly?
What am I missing here?
Have a read about memoization. The key insight is that if you've got a sequence starting A that has length 1001, and then you get a sequence B that produces an A, you don't to repeat all that work again.
This is the code in Mathematica, using memoization and recursion. Just four lines :)
f[x_] := f[x] = If[x == 1, 1, 1 + f[If[EvenQ[x], x/2, (3 x + 1)]]];
Block[{$RecursionLimit = 1000, a = 0, j},
Do[If[a < f[i], a = f[i]; j = i], {i, Reverse#Range#10^6}];
Print#a; Print[j];
]
Output .... chain length´525´ and the number is ... ohhhh ... font too small ! :)
BTW, here you can see a plot of the frequency for each chain length
Starting with 1,000,000, generate the chain. Keep track of each number that was generated in the chain, as you know for sure that their chain is smaller than the chain for the starting number. Once you reach 1, store the starting number along with its chain length. Take the next biggest number that has not being generated before, and repeat the process.
This will give you the list of numbers and chain length. Take the greatest chain length, and that's your answer.
I'll make some code to clarify.
public static long nextInChain(long n) {
if (n==1) return 1;
if (n%2==0) {
return n/2;
} else {
return (3 * n) + 1;
}
}
public static void main(String[] args) {
long iniTime=System.currentTimeMillis();
HashSet<Long> numbers=new HashSet<Long>();
HashMap<Long,Long> lenghts=new HashMap<Long, Long>();
long currentTry=1000000l;
int i=0;
do {
doTry(currentTry,numbers, lenghts);
currentTry=findNext(currentTry,numbers);
i++;
} while (currentTry!=0);
Set<Long> longs = lenghts.keySet();
long max=0;
long key=0;
for (Long aLong : longs) {
if (max < lenghts.get(aLong)) {
key = aLong;
max = lenghts.get(aLong);
}
}
System.out.println("number = " + key);
System.out.println("chain lenght = " + max);
System.out.println("Elapsed = " + ((System.currentTimeMillis()-iniTime)/1000));
}
private static long findNext(long currentTry, HashSet<Long> numbers) {
for(currentTry=currentTry-1;currentTry>=0;currentTry--) {
if (!numbers.contains(currentTry)) return currentTry;
}
return 0;
}
private static void doTry(Long tryNumber,HashSet<Long> numbers, HashMap<Long, Long> lenghts) {
long i=1;
long n=tryNumber;
do {
numbers.add(n);
n=nextInChain(n);
i++;
} while (n!=1);
lenghts.put(tryNumber,i);
}
Suppose you have a function CalcDistance(i) that calculates the "distance" to 1. For instance, CalcDistance(1) == 0 and CalcDistance(13) == 9. Here is a naive recursive implementation of this function (in C#):
public static int CalcDistance(long i)
{
if (i == 1)
return 0;
return (i % 2 == 0) ? CalcDistance(i / 2) + 1 : CalcDistance(3 * i + 1) + 1;
}
The problem is that this function has to calculate the distance of many numbers over and over again. You can make it a little bit smarter (and a lot faster) by giving it a memory. For instance, lets create a static array that can store the distance for the first million numbers:
static int[] list = new int[1000000];
We prefill each value in the list with -1 to indicate that the value for that position is not yet calculated. After this, we can optimize the CalcDistance() function:
public static int CalcDistance(long i)
{
if (i == 1)
return 0;
if (i >= 1000000)
return (i % 2 == 0) ? CalcDistance(i / 2) + 1 : CalcDistance(3 * i + 1) + 1;
if (list[i] == -1)
list[i] = (i % 2 == 0) ? CalcDistance(i / 2) + 1: CalcDistance(3 * i + 1) + 1;
return list[i];
}
If i >= 1000000, then we cannot use our list, so we must always calculate it. If i < 1000000, then we check if the value is in the list. If not, we calculate it first and store it in the list. Otherwise we just return the value from the list. With this code, it took about ~120ms to process all million numbers.
This is a very simple example of memoization. I use a simple list to store intermediate values in this example. You can use more advanced data structures like hashtables, vectors or graphs when appropriate.
Minimize how many levels deep your loops are, and use an efficient data structure such as IList or IDictionary, that can auto-resize itself when it needs to expand. If you use plain arrays they need to be copied to larger arrays as they expand - not nearly as efficient.
This variant doesn't use an HashMap but tries only to not repeat the first 1000000 numbers. I don't use an hashmap because the biggest number found is around 56 billions, and an hash map could crash.
I have already done some premature optimization. Instead of / I use >>, instead of % I use &. Instead of * I use some +.
void Main()
{
var elements = new bool[1000000];
int longestStart = -1;
int longestRun = -1;
long biggest = 0;
for (int i = elements.Length - 1; i >= 1; i--) {
if (elements[i]) {
continue;
}
elements[i] = true;
int currentStart = i;
int currentRun = 1;
long current = i;
while (current != 1) {
if (current > biggest) {
biggest = current;
}
if ((current & 1) == 0) {
current = current >> 1;
} else {
current = current + current + current + 1;
}
currentRun++;
if (current < elements.Length) {
elements[current] = true;
}
}
if (currentRun > longestRun) {
longestStart = i;
longestRun = currentRun;
}
}
Console.WriteLine("Longest Start: {0}, Run {1}", longestStart, longestRun);
Console.WriteLine("Biggest number: {0}", biggest);
}

Resources