Numerical sequence of 1 2 4 - algorithm

I need help in providing an algorithm for a numerical sequence which should display a series of 1 2 4 and its consecutive summations.
e.g. If my input value is 20, it should display
1 2 4 8 9 11 15 16 18
Wherein
1 = 1
2 = 1 + 1
4 = 2 + 2
8 = 4 + 4
And the summation of 1 and 2 and 4 will repeat again starting with the present number which is 8 and so on..
9 = 8 + 1
11 = 9 + 2
15 = 11 + 4
16 = 15 + 1
18 = 16 + 2
As you can see, it should not proceed to 22 (18 + 4) since our sample input value is 20. I hope you guys get my point. I'm having a problem in designing the algorithms in the for loop. What I have now which is not working is
$input = 20;
for ($i = $i; $i < $input; $i = $i+$i) {
if($i==0){
$i = 4;
$i = $i - 3;
}elseif($i % 4 == 0){
$i = $i + 1;
}
print_r("this is \$i = $i<br><br>");
}
NOTE: Only one variable and one for loop is required, it will not be accepted if we use functions or arrays. Please help me, this is one of the most difficult problems I've encountered in PHP..

you can use the code
$input = 20;
$current = 1;
$val = 1;
while($val < $input){
print_r("this is \$val = $val\n");
$val = $val + $current;
$current = ($current == 4 ? 1 : $current*2);
}
see the online compiler

Since you have mentioned Only one variable and one for loop is required
Try this,
$input = 20;
for ($i = 1; $i < $input; $i) {
if($i>$input) break;
print_r("this is \$i = $i<br><br>");
$i=$i+1;
if($i>$input) break;
print_r("this is \$i = $i<br><br>");
$i=$i+2;
if($i>$input) break;
print_r("this is \$i = $i<br><br>");
$i=$i+4;
}
Online Compiler

def getSeq(n):
if n == 1:
return [1]
temp = [1]
seq = [ 1, 2, 4]
count, current, prev = 0, 0, 1
while True:
current = prev + seq[count]
if current > n:
break
prev = current
temp += [current]
count = (count + 1) % 3
return temp
print getSeq(20)
I'm pretty sure that this one is going to work
the case that we have to take care of is n == 1 and return a static result [1].
in other cases the second value is repeating circularly and adding up to previous value.

This Python solution should be implementable in any reasonable language:
limit = 20
n = 1 << 2
while n >> 2 < limit:
print(n >> 2)
n = (((n >> 2) + (2 ** (n & 3))) << 2) + ((n & 3) + 1) % 3
Perl Equivalent (using the style of for loop you expect):
$limit = 20;
for ($n = 1 << 2; $n >> 2 < $limit; $n = ((($n >> 2) + (2 ** ($n & 3))) << 2) + (($n & 3) + 1) % 3) {
print($n >> 2, "\n");
}
OUTPUT
1
2
4
8
9
11
15
16
18
EXPLANATION
The basic solution is this:
limit = 20
n = 1
i = 0
while n < limit:
print(n)
n = n + (2 ** i)
i = (i + 1) % 3
But we need to eliminate the extra variable i. Since i only cycles through 0, 1 and 2 we can store it in two bits. So we shift n up two bits and store the value for i in the lower two bits of n, adjusting the code accordingly.
Not only one variable and one for loop, no if statements either!

Related

Gold Mine Problem - Sequence of for loops

Gold mine problem. Following sequence for loop is giving correct result.
//see link for other code
static int getMaxGold(int gold[][], int m, int n) {
//see link for other code
for (int col = n-1; col >= 0; col--) {
for (int row = 0; row < m; row++) {
int right = (col == n-1) ? 0 : goldTable[row][col+1];
int right_up = (row == 0 || col == n-1) ? 0 : goldTable[row-1][col+1];
int right_down = (row == m-1 || col == n-1) ? 0 : goldTable[row+1][col+1];
goldTable[row][col] = gold[row][col] + Math.max(right, Math.max(right_up, right_down));
}
}
}
//see link for other code
While other way round does not give the expected result. For example
for (int col = 0; col < n; col ++) {
for (int row = 0; row < m; row++) {
//same code to calculate right, rightUp and rightDown
}
}
Any explanation for this behaviour?
You don't need to store a whole matrix.
When you build the table, you just need to keep the last layer you processed.
In your recursion, there is diagonally right, or right, so the layer is a column because to compute the value of some cell, you need to know three values (on its right)
You conclude (as spotted by Damien already) that you start from the rightmost column, then to compute the value of every cells of the n-1 column, you only need to know the nth column (which you luckily computed already)
In below example. m_ij refers to i-th line, j-th column. (e.g m_01 == 2, m_10 = 5)
1 2 3 4
5 6 7 8
9 1 2 3
4 5 6 3
The last column is {4,8,3,3}
To compute the max value for m_02 you need to choose between 4 and 8
3 - 4
\
8
m_02 = 3 + 8 = 11
To compute the max value of m_12 you need to choose between 4, 8 and 3
4
/
7 - 8
\
3
m_12 = 7 + 8 = 15
Skipping stuff
m_22 = 2 + 8 = 10
m_32 = 6 + 3 = 9
Now you know the max value for each square of the third column
1 2 11 .
5 6 15 .
9 1 10 .
4 5 9 .
You do the same for m_10, m_11, ...
idem
m_01 = 2 + max(11, 15) = 17
m_11 = 6 + 15
m_21 = 1 + 15
m_31 = 5 + 10
Left to process is thus
1 17
5 21
9 16
4 15
Then
1+21
5+21
9+21
4+16
And finally score = max(22, 26, 30, 20)
As you have noticed you only need to keep track of the last processed column. Not a whole table of computation. And the last processed column must start from the right and always be the rightmost one...
I don't think an implem is relevant to help you understand but in case
const s = `
1 2 3 4
5 6 7 8
9 1 2 3
4 5 6 3`
const m = s.trim().split('\n').map(x => x.trim().split(' ').map(y => parseInt(y)))
let layer = [0, 0, 0, 0]
for (let j = 3; j >= 0; --j) {
const nextLayer = []
for (let i = 0; i < 4; ++i) {
nextLayer[i] = m[i][j] + Math.max(
layer[i-1] || 0, // we default undefined value as 0 supposing s only holds positive coefficient
layer[i],
layer[i+1] || 0
)
}
layer = nextLayer
}
console.log(Math.max(...layer))

Add all the values between 100 and 4000000 inclusively that are divisable by 3 or 5 but not both 3 and 5

Add all the values between 100 and 4000000 inclusively that are divisable by 3 or 5 but not both 3 and 5
Can't figure out how to implement second part of that stipulation. Here's what I have so far:
var sum = 0;
for (var i = 100; i < 4000001; i++) {
if (i % 3 || i % 5 === 0) {
sum = sum + i;
}
}
You can compute the sum without any loop, using the formula for the sum of an arithmetic progression: We have
3 + 5 + 6 + 9 + 10 + 12 + 18 + 20 + ...
= 3 + 6 + 9 + 12 + 15 + 18 + ...
+ 5 + 10 + 15 + 20 + ...
- 2*(15 + 30 + 45 + ...)
Note that we add all the multiples of 3 and 5 but then subtract the multiples of 15 twice, because they were counted twice as multiples of both 3 and 5.
Let g(n) be the sum of integers from 1 to n. We have g(n) = n*(n+1)/2.
Let f(n) be the sum of integers between 1 and n that are divisible by 3 or 5, but not both. Then we have
f(n) = 3*g(floor(n / 3)) + 5*g(floor(n/5)) - 30*g(floor(n/15))
And the sum of integers between m and n that are divisible by 3 or 5, but not both is then just f(n) - f(m - 1). This can be computed in O(1).
You simply need to escape only those part which involves division by 15, and other higher numbers(multiple of 15) will be avoided further automatically.
Note that checking divisibility by 15 should be at the top, which on being true will continue further iteration without executing the below codes of divisibility by 3 and 5. If false, then a number can only be divisible by 3 or 5 or none, but not both.
for (var i = 100; i < 4000001; i++) {
if(i % 15 == 0 )
continue;
if (i % 3 == 0) {
sum = sum + i;
}
if (i % 5 == 0) {
sum = sum + i;
}
}
Also, note that you have used === operator which I don't think is a valid operator, probably you want ==. BTW, I am not sure whether any language supports ===, I think Javascript supports that. So, be careful at that step.
You can use != instead of || since this is exactly what you want. Only divisible by 3 or 5 but not by both.
var sum = 0;
for (var i = 100; i < 4000001; i++) {
if ((i % 3 == 0) != (i % 5 == 0)) {
sum = sum + i;
}
}
var sum = 0;
for (var i = 100; i < 4000001; i++) {
if (i % 3 === 0 ^ i % 5 === 0) {
sum = sum + i;
}
}
use the exclusive OR , XOR ^ returns true only when one of the conditions not both is true.

Maximum length of zigzag sequence

A sequence of integers is called zigzag sequence if each of its elements is either strictly less or strictly greater than its neighbors.
Example : The sequence 4 2 3 1 5 3 forms a zigzag, but 7 3 5 5 2 and 3 8 6 4 5 don't.
For a given array of integers we need to find the length of its largest (contiguous) sub-array that forms a zigzag sequence.
Can this be done in O(N) ?
Currently my solution is O(N^2) which is just simply taking every two points and checking each possible sub-array if it satisfies the condition or not.
I claim that the length of overlapping sequence of any 2 zigzag sub-sequences is a most 1
Proof by contradiction:
Assume a_i .. a_j is the longest zigzag sub-sequence, and there is another zigzag sub-sequence b_m...b_n overlapping it.
without losing of generality, let's say the overlapping part is
a_i ... a_k...a_j
--------b_m...b_k'...b_n
a_k = b_m, a_k+1 = b_m+1....a_j = b_k' where k'-m = j-k > 0 (at least 2 elements are overlapping)
Then they can merge to form a longer zig-zag sequence, contradiction.
This means the only case they can be overlapping each other is like
3 5 3 2 3 2 3
3 5 3 and 3 2 3 2 3 is overlapping at 1 element
This can still be solved in O(N) I believe, like just greedily increase the zig-zag length whenever possible. If fails, move iterator 1 element back and treat it as a new zig-zag starting point
Keep record the latest and longest zig-zag length you have found
Walk along the array and see if the current item belongs to (fits a definition of) a zigzag. Remember the las zigzag start, which is either the array's start or the first zigzag element after the most recent non-zigzag element. This and the current item define some zigzag subarray. When it appears longer than the previously found, store the new longest zigzag length. Proceed till the end of array and you should complete the task in O(N).
Sorry I use perl to write this.
#!/usr/bin/perl
#a = ( 5, 4, 2, 3, 1, 5, 3, 7, 3, 5, 5, 2, 3, 8, 6, 4, 5 );
$n = scalar #a;
$best_start = 0;
$best_end = 1;
$best_length = 2;
$start = 0;
$end = 1;
$direction = ($a[0] > $a[1]) ? 1 : ($a[0] < $a[1]) ? -1 : 0;
for($i=2; $i<$n; $i++) {
// a trick here, same value make $new_direction = $direction
$new_direction = ($a[$i-1] > $a[$i]) ? 1 : ($a[$i-1] < $a[$i]) ? -1 : $direction;
print "$a[$i-1] > $a[$i] : direction $new_direction Vs $direction\n";
if ($direction != $new_direction) {
$end = $i;
} else {
$this_length = $end - $start + 1;
if ($this_length > $best_length) {
$best_start = $start;
$best_end = $end;
$best_length = $this_length;
}
$start = $i-1;
$end = $i;
}
$direction = $new_direction;
}
$this_length = $end - $start + 1;
if ($this_length > $best_length) {
$best_start = $start;
$best_end = $end;
$best_length = $this_length;
}
print "BEST $best_start to $best_end length $best_length\n";
for ($i=$best_start; $i <= $best_end; $i++) {
print $a[$i], " ";
}
print "\n";
For each index i, you can find the smallest j such that the subarray with index j,j+1,...,i-1,i is a zigzag. This can be done in two phases:
Find the longest "increasing" zig zag (starts with a[1]>a[0]):
start = 0
increasing[0] = 0
sign = true
for (int i = 1; i < n; i ++)
if ((arr[i] > arr[i-1] && sign) || )arr[i] < arr[i-1] && !sign)) {
increasing[i] = start
sign = !sign
} else if (arr[i-1] < arr[i]) { //increasing and started last element
start = i-1
sign = false
increasing[i] = i-1
} else { //started this element
start = i
sign = true
increasing[i] = i
}
}
Do similarly for "decreasing" zig-zag, and you can find for each index the "earliest" possible start for a zig-zag subarray.
From there, finding the maximal possible zig-zag is easy.
Since all oporations are done in O(n), and you basically do one after the other, this is your complexity.
You can combine the both "increasing" and "decreasing" to one go:
start = 0
maxZigZagStart[0] = 0
sign = true
for (int i = 1; i < n; i ++)
if ((arr[i] > arr[i-1] && sign) || )arr[i] < arr[i-1] && !sign)) {
maxZigZagStart[i] = start
sign = !sign
} else if (arr[i-1] > arr[i]) { //decreasing:
start = i-1
sign = false
maxZigZagStart[i] = i-1
} else if (arr[i-1] < arr[i]) { //increasing:
start = i-1
sign = true
maxZigZagStart[i] = i-1
} else { //equality
start = i
//guess it is increasing, if it is not - will be taken care of next iteration
sign = true
maxZigZagStart[i] = i
}
}
You can see that you can actually even let go of maxZigZagStart aux array and stored local maximal length instead.
A sketch of simple one-pass algorithm. Cmp compares neighbour elements, returning -1, 0, 1 for less, equal and greater cases.
Zigzag ends for cases of Cmp transitions:
0 0
-1 0
1 0
Zigzag ends and new series starts:
0 -1
0 1
-1 -1
1 1
Zigzag series continues for transitions
-1 1
1 -1
Algo:
Start = 0
LastCmp = - Compare(A[i], A[i - 1]) //prepare to use the first element individually
MaxLen = 0
for i = 1 to N - 1 do
Cmp = Compare(A[i], A[i - 1]) //returns -1, 0, 1 for less, equal and greater cases
if Abs(Cmp - LastCmp) <> 2 then
//zigzag condition is violated, series ends, new series starts
MaxLen = Max(MaxLen, i - 1 - Start)
Start = i
//else series continues, nothing to do
LastCmp = Cmp
//check for ending zigzag
if LastCmp <> 0 then
MaxLen = Max(MaxLen, N - Start)
examples of output:
2 6 7 1 7 0 7 3 1 1 7 4
5 (7 1 7 0 7)
8 0 0 3 5 8
1
0 0 7 0
2
1 2 0 7 9
3
8 3 5 2
4
1 3 7 1 6 6
2
1 4 0 6 6 3 4 3 8 0 9 9
5
Lets consider sequence 5 9 3 4 5 4 2 3 6 5 2 1 3 as an example. You have a condition which every internal element of subsequence should satisfy (element is strictly less or strictly greater than its neighbors). Lets compute this condition for every element of the whole sequence:
5 9 3 6 5 7 2 3 6 5 2 1 3
0 1 1 1 1 1 1 0 1 0 0 1 0
The condition is undefined for outermost elements because they have only one neighbor each. But I defined it as 0 for convenience.
The longest subsequence of 1's (9 3 6 5 7 2) is the internal part of the longest zigzag subsequence (5 9 3 6 5 7 2 3). So the algorithm is:
Find the longest subsequence of elements satisfying condition.
Add to it one element to each side.
The first step can be done in O(n) by the following algorithm:
max_length = 0
current_length = 0
for i from 2 to len(a) - 1:
if a[i - 1] < a[i] > a[i + 1] or a[i - 1] > a[i] < a[i + 1]:
current_length += 1
else:
max_length = max(max_length, current_length)
current_length = 0
max_length = max(max_length, current_length)
The only special case is if the sequence total length is 0 or 1. Then the whole sequence would be the longest zigzag subsequence.
#include "iostream"
using namespace std ;
int main(){
int t ; scanf("%d",&t) ;
while(t--){
int n ; scanf("%d",&n) ;
int size1 = 1 , size2 = 1 , seq1 , seq2 , x ;
bool flag1 = true , flag2 = true ;
for(int i=1 ; i<=n ; i++){
scanf("%d",&x) ;
if( i== 1 )seq1 = seq2 = x ;
else {
if( flag1 ){
if( x>seq1){
size1++ ;
seq1 = x ;
flag1 = !flag1 ;
}
else if( x < seq1 )
seq1 = x ;
}
else{
if( x<seq1){
size1++ ;
seq1=x ;
flag1 = !flag1 ;
}
else if( x > seq1 )
seq1 = x ;
}
if( flag2 ){
if( x < seq2 ){
size2++ ;
seq2=x ;
flag2 = !flag2 ;
}
else if( x > seq2 )
seq2 = x ;
}
else {
if( x > seq2 ){
size2++ ;
seq2 = x ;
flag2 = !flag2 ;
}
else if( x < seq2 )
seq2 = x ;
}
}
}
printf("%d\n",max(size1,size2)) ;
}
return 0 ;
}

Total probability of a given answer of a given number of additions [closed]

Closed. This question does not meet Stack Overflow guidelines. It is not currently accepting answers.
Questions asking for code must demonstrate a minimal understanding of the problem being solved. Include attempted solutions, why they didn't work, and the expected results. See also: Stack Overflow question checklist
Closed 9 years ago.
Improve this question
I'm doing C++, and I want to find out the simplest way to find the total probability of a given answer of a given number of additions.
For example, the given answer is 5, and the given number of additions is 4 (x+x+x+x). The total probability that I want to find is 4:
1) 1 + 1 + 1 + 2 = 5
2) 1 + 1 + 2 + 1 = 5
3) 1 + 2 + 1 + 1 = 5
4) 2 + 1 + 1 + 1 = 5
Another example, the given answer is 6, and the given number of additions is 4 (x+x+x+x). The total probability is 10:
1) 1 + 1 + 1 + 3 = 6
2) 1 + 1 + 3 + 1 = 6
3) 1 + 3 + 1 + 1 = 6
4) 3 + 1 + 1 + 1 = 6
5) 1 + 1 + 2 + 2 = 6
6) 1 + 2 + 2 + 1 = 6
7) 2 + 2 + 1 + 1 = 6
8) 2 + 1 + 1 + 2 = 6
9) 2 + 1 + 2 + 1 = 6
10) 1 + 2 + 1 + 2 = 6
I have absolutely no idea where to start
Here's a start for you.
Have a look at this table
1 2 3 4 5
+------------------
1 | 1 0 0 0 0
2 | 1 1 0 0 0
3 | 1 2 1 0 0
4 | 1 3 3 1 0
5 | 1 4 6 4 1
The number of summands is increasing from left to right, the total increases in rows, so e.g. there are 3 ways to sum 3 integers (greater than 0) for a total of 4 (namely 1+1+2, 1+2+1, 2+1+1).
With 4 additions and a result Y, if all numbers will be positive and nonzero and small enough (<100) you can easily at least bruteforce this... just cycle trough all numbers with 4x for cycles and if they sum up to Y increment number of permutations. Disadvantage is the complexity O(N^4) which will be very slow.
#include <iostream>
using namespace std;
int main()
{
int y = 6;
int perm = 0;
for(int a = 1; a < y; a++)
for(int b = 1; b < y; b++)
for(int c = 1; c < y; c++)
for(int d = 1; d < y; d++)
{
if((a+b+c+d)==y)
{
cout << a << " + " << b << " + " << c << " + " << d << " = " << y << endl;
perm++;
}
}
cout << "number of permutations: " << perm << endl;
}
This is not probability what you are trying to find, it's number of comibnations.
Looking at your examples, I assume that the number of numbers you are adding is fixed (i.e. 4), so every number is greater or equal to 1. We can do simple math here then - let's substract this number from both sides of the equation:
Original: 1) 1 + 1 + 1 + 2 = 5
Result of substracting: 1) 0 + 0 + 0 + 1 = 1
When the substraction is done, your problem is the combination with repetition problem.
The formulas you can find in the link I provided are quite simple. The problem can be solved using following code:
#include <iostream>
unsigned factorial(int n)
{
if (n == 1) return 1;
return n * factorial(n-1);
}
unsigned combinationsWithRepetition(int n, int k)
{
return factorial(n + k - 1) / (factorial(k) * factorial(n - 1));
}
unsigned yourProblem(unsigned numberOfNumbers, unsigned result)
{
return combinationsWithRepetition(numberOfNumbers, result - numberOfNumbers);
}
int main()
{
std::cout << yourProblem(4, 5) << std::endl;
std::cout << yourProblem(4, 6) << std::endl;
return 0;
}
Also, you can check this code out in online compiler.
Note that this code covers only the problem solving and could be improved if you choose to use it (i.e. it is not protected against invalid values).

Formula needed: Sort array to array-"snaked"

After the you guys helped me out so gracefully last time, here is another tricky array sorter for you.
I have the following array:
a = [1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16]
I use it for some visual stuff and render it like this:
1 2 3 4
5 6 7 8
9 10 11 12
13 14 15 16
Now I want to sort the array to have a "snake" later:
// rearrange the array according to this schema
1 2 3 4
12 13 14 5
11 16 15 6
10 9 8 7
// the original array should look like this
a = [1,2,3,4,12,13,14,5,11,16,15,6,10,9,8,7]
Now I'm looking for a smart formula / smart loop to do that
ticker = 0;
rows = 4; // can be n
cols = 4; // can be n
originalArray = [1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16];
newArray = [];
while(ticker &#60 originalArray.length)
{
//do the magic here
ticker++;
}
Thanks again for the help.
I was bored, so I made a python version for you with 9 lines of code inside the loop.
ticker = 0
rows = 4
cols = 4
originalArray = [1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16]
newArray = [None] * (rows * cols)
row = 0
col = 0
dir_x = 1
dir_y = 0
taken = {}
while (ticker < len(originalArray)):
newArray[row * cols + col] = originalArray[ticker]
taken[row * cols + col] = True
if col + dir_x >= cols or row + dir_y >= rows or col + dir_x < 0:
dir_x, dir_y = -dir_y, dir_x
elif ((row + dir_y) * cols + col + dir_x) in taken:
dir_x, dir_y = -dir_y, dir_x
row += dir_y
col += dir_x
ticker += 1
print newArray
You can index into the snake coil directly if you recall that
1 + 2 + 3 + ... + n = n*(n+1)/2
m^2 + m - k = 0 => m - (-1+sqrt(1+4*k))/2
and look at the pattern of the coils. (I'll leave it as a hint for the time being--you could also use that n^2 = (n-1)^2 + (2*n+1) with reverse-indexing, or a variety of other things to solve the problem.)
When translating to code, it's not really any shorter than Tuomas' solution if all you want to do is fill the matrix, however.

Resources