Counting Unique Paths in an Array with Special Rules - recursion

Description of the Problem:
I have an array of two-digit numbers going from 00 to 99. I must choose a number at random anywhere in the array; let's call this result r. I may now take up to n steps within the array to "travel" to another number in the array, according to the following rules:
Adding or subtracting 1 from r takes one (1) step; I cannot add 1 if there is a 9 in the ones place (ex: 09, 19, 29, ...) and I cannot subtract 1 if there is a 0 in the ones place (ex: 00, 10, 20, ...)
Adding or subtracting 10 from r takes one (1) step; I cannot bring the result to lower than 00 or higher than 99.
By taking two (2) steps, I can swap the digits in the ones and tens place (ex: 13 -> 31, 72 -> 27); however, I can't perform the swap if the digits are the same (ex: can't swap 00, 11, 22, ...)
For a given number x (00 <= x <= 99) I want to count the set of unique values of r from which I can travel to x, given that I can take between 0 and n steps. I call this count how "accessible" x is. I'd like to express this as a formula, A(x, n), rather than just brute-forcing the results for each combination of x and n.
What I Have Tried:
A(x, 0) is easy enough to calculate: A(x, 0) = 1 for all values in the array, because the only way to reach x from r is for r = x; I take zero (0) steps to reach it.
A(x, 1) is trickier, but still simple: you just take into account the new paths available if I spend my one step on either Rule #1 or Rule #2, and add them to A(x, 0). A(x, 2) is where I have to start including Rule #3, but also includes the problem of backtracking. For instance, if I want to reach x and x = r, and I have two (2) steps available, I could perform the following operation: Step 1, r -> r' = r+1 (Rule #1); Step 2, r' -> r'' = r'-1 (Rule #1); r'' = x AND r'' = r. This does not add to my count of unique values from which I can travel to x from.
Where I am Stuck:
I cannot figure out how to count the number of backtracking paths in order to remove them from the otherwise simple calculations of A(x, n), so my values of accessibility are coming out too high.

Related

What is the most efficient way to find all pairs of numbers from a list of integers which add up to a separate given integer?

I had an interview yesterday and was asked to give a method to find all of the pairs of numbers from a list which add up to an integer which is given separate to the list. The list can be infinitely long, but for example:
numbers = [11,1,5,27,7,18,2,4,8]
sum = 9
pairs = [(1,8),(5,4),(7,2)]
I got as far as sorting the list and eliminating all numbers greater than the sum number and then doing two nested for loops to take each index and iterate through the other numbers to check whether they sum up to the given number, but was told that there was a more efficient way of doing it...
I've been trying to figure it out but have nothing, other than doing the nested iteration backwards but that only seems marginally more efficient.
Any ideas?
This can be done in O(n) time and O(n) auxiliary space; testing for membership of a set takes O(1) time. Since the output also takes up to O(n) space, the auxiliary space should not be a significant issue.
def pairs_sum(numbers, k):
numbers_set = set(numbers)
return [(x, y) for x in numbers if (y := k - x) in numbers_set and x < y]
Example:
>>> pairs_sum([11, 1, 5, 27, 7, 18, 2, 4, 8], 9)
[(1, 8), (2, 7), (4, 5)]
It is kind of a classic and not sure stackoverflow is the right place to ask that kind of question.
Sort the list is acsending order
Two iterators one starting from the end of the list descending i1, one starting from the beginning of the list ascending i2
Loop
while i1 > i2
if (list[i1] + list[i2] == target)
store {list[i1], list[i2]) in results pairs
i1--
i2++
else if (list[i1] + list[i2] > target)
i1--
else if (list[i1] + list[i2] < target)
i2++
This should be in O(n) with n the length of the list if you avoid the sorting algorithm which can be done with a quick sort on average in O(n log n)
Note: this algorithm doesn't take into account the case where the input list have several times the same number

Statistical probability of N contiguous true-bits in a sequence of bits?

Let's assume I have an N-bit stream of generated bits. (In my case 64kilobits.)
Whats the probability of finding a sequence of X "all true" bits, contained within a stream of N bits. Where X = (2 to 16), and N = (16 to 1000000), and X < N.
For example:
If N=16 and X=5, whats the likelyhood of finding 11111 within a 16-bit number.
Like this pseudo-code:
int N = 1<<16; // (64KB)
int X = 5;
int Count = 0;
for (int i = 0; i < N; i++) {
int ThisCount = ContiguousBitsDiscovered(i, X);
Count += ThisCount;
}
return Count;
That is, if we ran an integer in a loop from 0 to 64K-1... how many times would 11111 appear within those numbers.
Extra rule: 1111110000000000 doesn't count, because it has 6 true values in a row, not 5. So:
1111110000000000 = 0x // because its 6 contiguous true bits, not 5.
1111100000000000 = 1x
0111110000000000 = 1x
0011111000000000 = 1x
1111101111100000 = 2x
I'm trying to do some work involving physically-based random-number generation, and detecting "how random" the numbers are. Thats what this is for.
...
This would be easy to solve if N were less than 32 or so, I could just "run a loop" from 0 to 4GB, then count how many contiguous bits were detected once the loop was completed. Then I could store the number and use it later.
Considering that X ranges from 2 to 16, I'd literally only need to store 15 numbers, each less than 32 bits! (if N=32)!
BUT in my case N = 65,536. So I'd need to run a loop, for 2^65,536 iterations. Basically impossible :)
No way to "experimentally calculate the values for a given X, if N = 65,536". So I need maths, basically.
Fix X and N, obiously with X < N. You have 2^N possible values of combinations of 0 and 1 in your bit number, and you have N-X +1 possible sequences of 1*X (in this part I'm only looking for 1's together) contained in you bit number. Consider for example N = 5 and X = 2, this is a possible valid bit number 01011, so fixed the last two characteres (the last two 1's) you have 2^2 possible combinations for that 1*Xsequence. Then you have two cases:
Border case: Your 1*X is in the border, then you have (2^(N -X -1))*2 possible combinations
Inner case: You have (2^(N -X -2))*(N-X-1) possible combinations.
So, the probability is (border + inner )/2^N
Examples:
1)N = 3, X =2, then the proability is 2/2^3
2) N = 4, X = 2, then the probaility is 5/16
A bit brute force, but I'd do something like this to avoid getting mired in statistics theory:
Multiply the probabilities (1 bit = 0.5, 2 bits = 0.5*0.5, etc) while looping
Keep track of each X and when you have the product of X bits, flip it and continue
Start with small example (N = 5, X=1 - 5) to make sure you get edge cases right, compare to brute force approach.
This can probably be expressed as something like Sum (Sum 0.5^x (x = 1 -> 16) (for n = 1 - 65536) , but edge cases need to be taken into account (i.e. 7 bits doesn't fit, discard probability), which gives me a bit of a headache. :-)
#Andrex answer is plain wrong as it counts some combinations several times.
For example consider the case N=3, X=1. Then the combination 101 happens only 1/2^3 times but the border calculation counts it two times: one as the sequence starting with 10 and another time as the sequence ending with 01.
His calculations gives a (1+4)/8 probability whereas there are only 4 unique sequences that have at least a single contiguous 1 (as opposed to cases such as 011):
001
010
100
101
and so the probability is 4/8.
To count the number of unique sequences you need to account for sequences that can appear multiple times. As long as X is smaller than N/2 this will happens. Not sure how you can count them tho.

Return the ith number of the format x^y, where x and y are integers

x and y are integers greater than 1.
A Special number can be expressed as x^y.
Note that the special number sequence is in ascending order (4, 8, 9, 16, 25, 27, 32, ...).
Given an integer i, the program should return the ith special number.
i=0 -> num=4
i=4 -> num=25
Would like some insights. Faced this in a coding round for a company. Brute force ended up with TLEs.
Edit 1: Found a link: https://codegolf.stackexchange.com/questions/78985/find-the-n-th-perfect-power.
Edit-2: I shared the codegolf link to help check some of the solutions that are already available and are expected to exceed the time limit. I tried both with the Mathematica solution and the sage solution approach, faced TLE on both of them.
This problem is equivalent to finding an integer j where log_j k is an integer, and j is in a sequence with an upper bound k such that sum [floor(log_j k) - 1 | j <- [2..floor(sqrt k)] == i
We can make a rough estimate of where the ith element would be by binary search with a limited iteration. If we guess the number at m^2, the highest base that may be counted is:
m
Then we can examine lower bases and add up their log counts. For example, i = 10:
Guess: 10^2
Highest base: 10
Then at minimum we have (10 - 1) + (floor(log2 (10^2)) - 1)
= 15 elements. Too many.
Guess: 5^2
Highest base: 5
Minimum element count: (5 - 1) + (floor(log2 (5^2)) - 1) = 8
Iterate over logs:
-- Because of the exponential nature of the problem,
-- if the guess is too large, the bulk of the elements will appear
-- early in the iteration; and if it's too small, the limit on
-- exponents will drop early allowing for early exit in either case.
[floor(logBase x 25) - 1 | x <- [2..4]] = [3,1,1]
sum ([1] ++ [3,1,1]) = 6. Too few.
Guess: 7^2
Highest base: 7
Minimum element count: (7 - 1) + (floor(log2 (7^2)) - 1) = 10
Iterate over logs:
[floor(logBase x 49) - 1 | x <- [2..6]] = [4,2,1,1,1]
sum ([1] ++ [4,2,1,1,1]) = 10
Answer: 7^2

All numbers in a given range but random order

Let's say I want to generate all integers from 1-1000 in a random order. But...
No numbers are generated more then once
Without storing an Array, List... of all possible numbers
Without storing the already generated numbers.
Without missing any numbers in the end.
I think that should be impossible but maybe I'm just not thinking about the right solution.
I would like to use it in C# but I'm more interested in the approche then the actual implementation.
Encryption. An encryption is a one-to-one mapping between two sets. If the two sets are the same, then it is a permutation specified by the encryption key. Write/find an encryption that maps {0, 1000} onto itself. Read up on Format Preserving Encryption (FPE) to help you here.
To generate the random order just encrypt the numbers 0, 1, 2, ... in order. You don't need to store them, just keep track of how far you have got through the list.
From a practical point of view, numbers in {0, 1023} would be easier to deal with as that would be a block cipher with a 10 bit block size, and you could write a simple Feistel cipher to generate your numbers. You might want to do that anyway, and just re-encrypt numbers above 1000 -- the cycle walking method of FPE.
If randomness isn't a major concern, you could use a linear congruential generator. Since an LCG won't produce a maximal length sequences when the modulus is a prime number, you would need to choose a larger modulus (the next highest power of 2 would be an obvious choice) and skip any values outside the required range.
I'm afraid C# isn't really my thing, but hopefully the following Python is self-explanatory. It will need a bit of tweaking if you want to generate sequences over very small ranges:
# randint(a, b) returns a random integer in the range (a..b) (inclusive)
from random import randint
def lcg_params(u, v):
# Generate parameters for an LCG that produces a maximal length sequence
# of numbers in the range (u..v)
diff = v - u
if diff < 4:
raise ValueError("Sorry, range must be at least 4.")
m = 2 ** diff.bit_length() # Modulus
a = (randint(1, (m >> 2) - 1) * 4) + 1 # Random odd integer, (a-1) divisible by 4
c = randint(3, m) | 1 # Any odd integer will do
return (m, a, c, u, diff + 1)
def generate_pseudorandom_sequence(rmin, rmax):
(m, a, c, offset, seqlength) = lcg_params(rmin, rmax)
x = 1 # Start with a seed value of 1
result = [] # Create empty list for output values
for i in range(seqlength):
# To generate numbers on the fly without storing them in an array,
# just run the following while loop to fetch a new number
while True:
x = (x * a + c) % m # Iterate LCG until we get a value in the
if x < seqlength: break # required range
result.append(x + offset) # Add this value to the list
return result
Example:
>>> generate_pseudorandom_sequence(1, 20)
[4, 6, 8, 1, 10, 3, 12, 5, 14, 7, 16, 9, 18, 11, 20, 13, 15, 17, 19, 2]

Number of Zero-crossings - Equation

I have written an algorithm that calculates the number of zero-crossings within a signal. By this, I mean the number of times a value changes from + to - and vice-versa.
The algorithm is explained like this:
If there are the following elements:
v1 = {90, -4, -3, 1, 3}
Then you multiply the value by the value next to it. (i * i+1)
Then taking the sign value sign(val) determine if this is positive or negative. Example:
e1 = {90 * -4} = -360 -> sigum(e1) = -1
e2 = {-4 * -3} = 12 -> signum(e2) = 1
e3 = {-3 * 1} = -3 -> signum(e3) = -1
e4 = {1 * 3} = 3 -> signum(e4) = 1
Therefore the total number of values changed from negative to positive is = 2 ..
Now I want to put this forumular, algorithm into an equation so that I can present it.
I have asked a simular question, but got really confused so went away and thought about it and came up with (what I think the equation should look like).. It's probably wrong, well, laughably wrong. But here it is:
Now the logic behind it:
I pass in a V (val)
I get the absolute value of the summation of the signum from calculating (Vi * Vi+1) .. The signum(Vi * Vi+1) should produce -1, 1, ..., values
If and only if the value is -1 (Because I'm only interested in the number of times zero is crossed, therefore, the zero values.
Does this look correct, if not, can anyone suggest improvements?
Thank you :)!
EDIT:
Is this correct now?
You are doing the right thing here but your equation is wrong simply because you only want to count the sign of the product of adjacent elements when it is negative. Dont sum the sign of products since positive sign products should be neglected. For this reason, an explicit mathematical formula is tricky as positive products between adjacent elements should be ignored. What you want is a function that takes 2 arguments and evaluates to 1 when their product is negative and zero when non-negative
f(x,y) = 1 if xy < 0
= 0 otherwise
then your number of crossing points is simply given by
sum(f(v1[i],v1[i+1])) for i = 0 to i = n-1
where n is the length of your vector/array v1 (using C style array access notation based on zero indexing). You also have to consider edge conditions such as 4 consecutive points {-1,0,0,1} - do you want to consider this as simply one zero crossing or 2??? Only you can answer this based on the specifics of your problem, but whatever your answer adjust your algorithm accordingly.

Resources