Find the result of a function - recursion

There is a code of an unknown function:
function Magic(number)
r = number mod 2
print r
if number > 1
Magic(number / 2)
(written in pseudo-code)
The question is: what integer number should be passed in order to receive the following answer
0 1 1 0 0 1
The main problem is that I can't figure out how mod is working in pseudocode.
Should 5,5 mod 3 = 2.5 or 2

Both division and mod operations are only supposed to accept and output integer numbers here. "5.5 mod 3" f.e. doesn't really make any sense. And 11 / 2 (integer division) will return 5, not 5.5.
Here's a PHP program that implements your pseudo code:
<?php
function Magic($number) {
$r = $number % 2;
echo $r . ' ';
if ($number > 1) Magic($number / 2);
}
for ($i = 16; $i < 34; ++$i) {
echo "($i: ";
Magic($i);
echo ") ";
}
echo "\n";
Results in output:
(16: 0 0 0 0 1 ) (17: 1 0 0 0 1 0 ) (18: 0 1 0 0 1 0 ) (19: 1 1 0 0 1 0 ) (20: 0 0 1 0 1 0 ) (21: 1 0 1 0 1 0 ) (22: 0 1 1 0 1 0 ) (23: 1 1 1 0 1 0 ) (24: 0 0 0 1 1 0 ) (25: 1 0 0 1 1 0 ) (26: 0 1 0 1 1 0 ) (27: 1 1 0 1 1 0 ) (28: 0 0 1 1 1 0 ) (29: 1 0 1 1 1 0 ) (30: 0 1 1 1 1 0 ) (31: 1 1 1 1 1 0 ) (32: 0 0 0 0 0 1 ) (33: 1 0 0 0 0 1 0 )
Which shows that the 6-digit result (x: 0 1 1 0 0 1 ) is impossible for any integer x (because of the monotonic growth of the output string). However, Magic(38) is 0 1 1 0 0 1 0 — the first 7-digit result with your required string, but also having a trailing zero.
As for the negative integer values, the only 2 outputs possible are "0 ", and "-1 ".

First of all, here is executable python code for this problem.
def Magic(number):
r = number % 2
print r
if number > 1:
Magic(number / 2)
Magic(15)
However, the pattern in this problem is that the function is returning the REVERSE binary number for the given input number. So, in this instance, the easiest solution would be to take 0 1 1 0 0 1, reverse it to 100110, and calculate the value of that binary number, which is 32 + 4 + 2 = 38. Using this methodology, you can calculate the required number or the expected output for any given input.

mod gives you the remainder of a integer division. A few examples:
1 mod 2 = 1 (since 1 / 2 = 0 in integer division)
2 mod 2 = 0 (2 / 2 = 1, no remainder)
6 mod 3 = 0 (6 / 3 = 2, no remainder)
8 mod 3 = 2
The fraction part should probably be left out. in most languages it depends on the datatype of the number (some languages do integer division if both operands are integers, and this is probably what you should do too, so 5/2 = 2).
As to your first question (spoiler alert!, try it yourself before reading this!), begin from the end and multiply by two in every step. Also add 1 if the number should be 1 in that step.
So, the last step is a 1. Begin with 1:
1
1*2 = 2
2*2 = 4
4*2+1 = 9
and so on. I could give you the correct answer but I think it's better if you try it yourself ;-)

Related

What is the most optimal and creative way to create a random Matrix with mostly zeros and some ones in Julia?

I want to create a random Matrix with values of zeros and ones. With this presumption, there will be more zeros instead of ones! So I guess there should be something like a weighted Bernoulli distribution to choose between 0 or 1 each time (and more probability for choosing 0). I prefer not to limit it to just nxn matrices! I can try in an utterly not standard way like this:
julia> let mat = Matrix{Int64}(undef, 3, 5)
zero_or_one(shift) = rand()+shift>0.5 ? 0 : 1
foreach(x->mat[x]=zero_or_one(0.3), eachindex(mat))
end
julia> mat
3×5 Matrix{Int64}:
1 1 1 0 1
0 1 1 1 1
0 1 1 0 1
Note that this doesn't do the job. Because as you can see, I get more ones instead of zeros in the result.
Is there any more optimal or at least creative way? Or any module to do it?
Update:
It seems the result of this code will never change whether I change the value of shift or not 😑.
using SparseArrays?
julia> sprand(Bool, 1_000_000,1_000_000, 1e-9)
1000000×1000000 SparseMatrixCSC{Bool, Int64} with 969 stored entries:
⠀⠀⠁⠀⠢⠀⠂⠆⡄⠀⠀⠀⡈⠀⠐⠀⠁⠐⠂⠀⠀⢀⠤⠀⠀⠀⠄⠐⢀⠘⠈⠀⢂⠐⠀⠀⠆⠀⠠⠀⠀⠀⠀⢀⠈⠁⠀⠑⠀⢀⠐⠀
⠄⠀⡀⠀⠒⠠⠨⢀⣀⠀⠀⠀⠐⠤⠈⠀⠀⠀⠀⠀⠁⠁⠄⠐⠑⠅⢄⠠⠐⠀⠀⠀⠁⢀⠋⠂⠂⠂⠀⠀⠀⠀⠀⠀⠈⠄⠀⠀⠀⠄⠈⠀
⠠⠄⠀⢀⠀⢁⠐⠀⠁⠂⢂⠂⠀⠀⠠⠀⠀⠀⠁⠀⠈⠀⠀⠂⠀⠀⢀⠂⠀⠈⠀⠀⠀⠠⠀⠂⠄⠀⠄⠀⢀⠀⠀⠉⠀⠠⠤⠀⠒⡐⠀⠂
⢀⠂⠁⠀⠐⠀⠀⠀⠄⠀⢀⡘⠁⠂⠁⠀⠂⢀⠂⠅⡀⠀⠈⠡⠈⠉⢀⠩⠉⠄⡀⠀⠀⠐⠀⡀⡄⠈⠀⢀⠀⠂⠌⠀⠀⠂⠀⠀⠁⠀⠀⠀
⠂⠠⠀⡀⠀⢀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠂⠐⠀⠀⠂⡁⠁⠉⠈⠀⠀⠁⠀⠄⢀⠤⠀⠀⠁⡂⠠⠀⠄⠀⠀⡀⠀⢀⠥⠀⢉⠀⠀⠄⠁⠀
⠈⠀⠀⠀⠀⠅⠀⠀⠈⠀⠄⡄⠀⠀⠀⠠⠄⠈⠠⠀⠀⠐⠂⠀⠀⠀⠀⠆⠠⠀⠀⠀⠐⠀⠐⠀⠀⠀⠀⠀⠀⡀⠌⢠⠀⠀⠂⠐⠈⠀⠀⠐
⠀⡀⠁⠈⡀⠀⢀⠁⠈⠠⡈⠁⢄⠈⠀⠀⠀⢁⠐⣀⠂⠄⠄⢀⠠⠀⠐⠀⠡⠠⠄⠈⢄⢈⠂⠈⠆⠀⠁⠀⠀⠀⠃⠀⠀⠠⠀⠐⠀⠐⠘⡀
⠀⠂⠁⠰⠁⠀⠀⠀⠀⠄⠀⣐⠀⡄⠤⡀⠀⠄⠀⠐⠀⠉⠁⠀⠈⢀⣐⠠⠀⠀⠂⠀⠀⠀⠠⠂⠐⠁⠀⠀⠀⠐⡈⠀⠐⡀⠠⡁⡀⠠⡀⠈
⠈⠀⠀⠠⠀⠀⠀⠁⠠⠐⠀⠐⠄⡀⠠⠀⠀⠀⠐⡀⠀⠀⠄⠀⠀⢒⠈⠊⠀⢢⡠⠀⠀⠀⡈⠀⠀⠀⠀⠈⠉⠃⠀⡀⡉⠀⢁⠔⠀⠀⠂⠀
⠀⠀⠀⡐⠠⢀⠀⡐⠀⠈⢀⠀⠀⠀⠐⠪⠀⠂⡄⠐⠀⢀⠀⠈⠀⠀⠰⠀⠀⠀⠈⠀⠀⠠⠀⠀⠐⠀⠀⠠⠀⠀⡀⠄⠈⢂⠂⠌⠀⠀⠐⠀
⢀⠜⢈⠀⠤⠂⢄⠀⠘⠀⠀⠀⠈⠀⠀⢀⠄⠀⠠⠀⠠⠀⠀⠀⠁⠐⠁⠀⠀⠈⠁⠀⠀⢀⠀⢄⠀⠄⠀⠀⠀⠀⠀⡀⢄⠀⠅⠀⠀⠀⠀⠀
⠠⠦⠀⡐⠈⠐⠀⡄⠀⠄⠀⠀⠀⠀⡐⠀⠀⠌⠀⠨⠀⠀⠩⢀⠁⠀⠈⠐⠐⠀⠀⠀⠀⡐⠈⠀⠁⠘⠀⢀⠀⠀⠈⠀⠈⠀⠀⠐⠀⠐⠀⠈
⠀⠀⠀⢄⠤⠀⡀⠀⠀⠬⠀⠀⠂⡡⠀⠌⠠⠠⠀⠀⢀⢔⠀⠀⠀⠀⢀⠄⠀⡈⠀⠀⠈⠄⡀⠐⠀⠠⠀⠀⠠⠂⠠⠑⠀⠀⡄⢀⠁⠀⠀⢁
⠀⡀⠀⠀⠄⠀⠀⡀⠀⠀⠀⠄⠀⠂⠀⠁⠀⠀⠁⡠⠀⠀⠡⠀⠂⠂⠄⠀⣀⠄⠊⢀⠁⠀⠄⠀⠀⢀⠀⠄⠀⠁⡀⠈⠁⠀⠀⠀⢂⠀⠈⠂
⠀⠀⠀⢀⠀⠀⠀⠀⠀⠀⠠⡠⢐⠀⠀⠁⠀⠂⠀⠐⠀⠒⠈⡀⡂⢀⠀⠀⠀⠡⠌⠀⠀⢀⠄⠀⢐⠀⠀⢀⠠⠀⠀⠂⠀⠀⠈⠄⠠⡠⠀⡀
⢀⠲⠀⠀⠈⠀⠀⠂⠀⠀⠀⠀⠀⣀⠨⠁⢀⠀⠀⠀⠀⠀⠰⠀⠀⢠⠀⠁⠀⢀⢀⢀⠀⡡⠀⠈⠁⠀⠁⠠⠀⡀⠀⡀⠀⠐⠀⠐⠁⡀⠂⠈
⢀⠄⠀⠀⠀⠀⠡⠀⠀⠀⠀⠀⠀⠀⢀⠀⣂⠀⠀⠀⠂⠀⠀⠀⠀⠀⠁⠀⢀⠐⠀⠀⠐⠋⠀⠀⠀⢢⠠⠀⠂⠐⠄⢈⠠⠤⠀⡀⠀⠀⠀⠀
⠀⠠⠀⠄⢀⠄⠀⠑⠀⠀⠀⠄⠀⡠⠁⡀⢔⠠⢐⠀⢀⠀⠢⠀⠀⠈⠐⠀⠀⠀⠄⠂⠀⠀⠀⠀⠀⠀⡄⠀⡈⠀⠀⠀⡀⠀⠊⡀⠀⢠⠀⠀
⠀⠀⠒⠀⡀⢐⠄⡀⠀⠀⠀⠀⠀⠀⠀⠀⠀⡀⠁⠄⠀⠀⠀⠀⠀⡄⢀⡀⠀⠀⠀⠀⢀⢀⢀⠁⠁⠀⠁⠔⠀⠀⠀⠂⠀⠒⠀⢀⢈⢀⠀⠀
⠈⠀⠀⡂⠀⠁⢐⡀⠀⠀⠂⠀⠀⡂⠄⠊⠀⠀⠄⢀⠈⠈⠁⠀⠀⠈⠒⠀⠠⠑⠄⠀⠀⠀⠀⠀⠀⠀⠀⠀⣀⠄⠆⢄⠀⠀⠂⠂⠀⡀⠀⠀
⠀⠠⠄⠀⠀⠠⡀⠠⠀⠠⠀⠐⠀⠀⡌⠨⢀⠀⠀⠁⠀⠂⠀⡀⠄⠴⠀⢠⠄⠄⠄⡀⠀⠀⠂⢠⠀⠀⠀⠜⠐⠀⠀⠁⢠⠀⠄⠐⠁⠂⠀⠁
⠈⠀⠀⠀⠈⠐⠂⠈⠆⢈⠐⡀⠈⢀⠀⠐⠀⠰⠂⠀⠀⠀⠀⠀⠀⠠⠀⡂⠨⠀⠈⡀⠁⠀⠤⠈⠐⠂⠀⠀⡀⠀⠀⠀⠀⠢⠀⠠⠀⠀⠁⠀
⠠⠈⠀⠈⠠⡀⠀⠠⠀⠠⠀⠀⠐⢄⠜⠀⠈⠀⠄⡁⠀⠠⠀⠀⠀⠁⠀⠡⡀⠈⠐⠀⠂⠀⠀⠀⠀⠐⠐⡈⢀⡠⡂⠀⠀⠐⠀⠄⠀⠀⠀⠁
⢀⠁⠀⢠⠂⢁⠄⡅⠀⠠⠀⠄⠀⠠⠀⠈⡀⠈⠂⠀⠨⠈⢀⠀⢀⡈⠀⠈⡈⠂⠀⠈⠀⠀⡀⠀⠀⠀⠀⠀⠀⠊⠄⠠⠀⠀⠄⠊⠀⠈⠄⠀
⠂⠀⠀⠀⠌⠁⢀⠀⠐⠀⠀⠈⠀⠀⠁⠀⢀⠁⠪⠠⠀⠀⢐⠀⠀⠄⠀⠂⢀⡀⢐⠁⠀⣀⠒⠀⢀⢀⠀⠠⢂⠀⠀⠠⠀⠄⠐⠄⠁⠀⠀⠀
⠐⠀⠠⠀⠀⡀⠀⠄⠄⠐⠀⠁⠀⠀⠀⠀⠄⠄⠀⠀⢀⠂⠀⠰⠀⠀⠊⠀⢀⠀⠤⠀⠀⠀⠉⠀⠀⢀⠀⠁⠁⠀⠈⠁⠀⡠⡀⠐⠐⠀⠀⠀
I'd choose the Bernoulli distribution for this. Specify a success rate p, which takes value 1 with probability p and 0 with probability 1-p.
using Distributions
mat = rand(Bernoulli(0.1), 3, 4)
3×4 Matrix{Bool}:
1 0 0 0
0 0 0 0
0 0 0 0
As for your code, you chose rand()+shift>0.5 ? 0 : 1, that means if you write zero_or_one(0.3) it will give ones with probability 0.2 and zeros with probability 0.8, etc.
If you are OK with a BitMatrix:
julia> onesandzeros(shape...; threshold=0.5) = rand(shape...) .< threshold
onesandzeros (generic function with 1 method)
julia> onesandzeros(5, 8; threshold=0.2)
5×8 BitMatrix:
0 0 0 0 0 0 1 1
0 0 0 0 1 1 1 0
0 1 1 0 0 0 0 0
0 0 0 0 1 0 1 0
0 0 0 0 0 0 0 0
This amounts to sampling from a Binomial distribution.
If 0 and 1 should be equally probable, the default Binomial coefficient p = 0.5 encodes this:
julia> using Distributions
julia> rand(Binomial(), 3, 5)
3×5 Matrix{Int64}:
1 1 1 1 1
1 0 1 0 0
0 0 0 1 1
The number of 1s in the matrix is proportional to the parameter p, so if the matrix should on average contain ~10% 1 and ~90% 0, this is the same as sampling from Binomial(1, 0.1):
julia> rand(Binomial(1, 0.1), 3, 5)
3×5 Matrix{Int64}:
0 0 1 0 0
0 0 0 0 0
0 0 0 1 1
See also: Distributions.Binomial
Although based on some comments, I was somewhat convinced that the result of my code was reasonable, each time I investigated its simple procedure, I couldn't withdraw from focusing on it. I found the snag in my code. I forgot that the let blocks create a new hard scope area. So if I try returning the mat it would show a different and expected result for each run:
julia> let mat = Matrix{Int64}(undef, 3, 5)
zero_or_one(shift) = rand()+shift>0.5 ? 0 : 1
foreach(x->mat[x]=zero_or_one(0.3), eachindex(mat))
return mat
end
3×5 Matrix{Int64}:
0 0 0 0 1
0 0 0 0 0
1 0 0 1 0
Then, for making it available in the global scope, using a begin block will make the job get done:
julia> begin mat = Matrix{Int64}(undef, 3, 5)
zero_or_one(shift) = rand()+shift>0.5 ? 0 : 1
foreach(x->mat[x]=zero_or_one(0.3), eachindex(mat))
end
julia> mat
3×5 Matrix{Int64}:
0 1 0 0 1
0 0 0 0 0
1 0 0 1 0
(Note that the above results aren't precisely the same.)

Compute combination of a pair variables for a given operation in R

From a given dataframe:
# Create dataframe with 4 variables and 10 obs
set.seed(1)
df<-data.frame(replicate(4,sample(0:1,10,rep=TRUE)))
I would like to compute a substract operation between in all columns combinations by pairs, but only keeping one substact, i.e column A- column B but not column B-column A and so on.
What I got is very manual, and this tend to be not so easy when there are lots of variables.
# Result
df_result <- as.data.frame(list(df$X1-df$X2,
df$X1-df$X3,
df$X1-df$X4,
df$X2-df$X3,
df$X2-df$X4,
df$X3-df$X4))
Also the colname of the feature name should describe the operation i.e.(x1_x2) being x1-x2.
You can use combn:
COMBI = combn(colnames(df),2)
res = data.frame(apply(COMBI,2,function(i)df[,i[1]]-df[,i[2]]))
colnames(res) = apply(COMBI,2,paste0,collapse="minus")
head(res)
X1minusX2 X1minusX3 X1minusX4 X2minusX3 X2minusX4 X3minusX4
1 0 0 -1 0 -1 -1
2 1 1 0 0 -1 -1
3 0 0 0 0 0 0
4 0 0 -1 0 -1 -1
5 1 1 1 0 0 0
6 -1 0 0 1 1 0

Updating 0 vector values based on preceding and successive values

I have a data frame which has a cumulative count for each event (an event in this case being represented by a sequence of 1's in the bin column) with separating values given the value 0 and each event given an ID as such:
bin cumul ID
0 0 0
1 1 3
1 1 3
1 1 3
1 1 3
0 0 0
0 0 0
0 0 0
0 0 0
1 2 2
1 2 2
1 2 2
1 2 2
1 2 2
0 0 0
0 0 0
0 0 0
0 0 0
1 3 1
1 3 1
1 3 1
I want to update the ID column so each non-event (0 in the bin column) is assigned an ID value based on the previous and subsequent ID.
Therefore, if a non-event is preceded and succeeded by events of equal ID values (e.g. both 3) the non-event also carries this ID value (3). However if the non-event is preceded by an event with one value but succeeded with an event with a different value then the first half of the non-event is given an ID value equal to the preceding event and the final half of the non-event is given an ID value equal to the ID value of the succeeding event. Giving the final data frame:
bin cumul ID
0 0 3
1 1 3
1 1 3
1 1 3
1 1 3
0 0 3
0 0 3
0 0 2
0 0 2
1 2 2
1 2 2
1 2 2
1 2 2
1 2 2
0 0 2
0 0 2
0 0 1
0 0 1
1 3 1
1 3 1
1 3 1
If the question were how to fill in the zeros with ID that matched the preceding values, or matched successive values, then you could use na.locf from the zoo-package and it would be a one liner. For this task I think you might reach for the rle function:
rle(dat$ID)
#Run Length Encoding
# lengths: int [1:6] 1 4 4 5 4 3
# values : int [1:6] 0 3 0 2 0 1
Then thinking about how to use such result, my thinking was to use an algorithm like:
for each '0' in values; assign the first [`length`/2 + .9] values as $values[ idx-1 ]
assign the next ]`length`/2] values as $values[ idx+1 ]
( using `rep` will truncate/floor the fractional indices and adding a number
slightly less than 1.0 will take care of the edge cases where there are an
odd number of zeros in a row.)
( `sum` on the lengths can recover the correct positions.)
and for the beginning and ending 0-cases;
replace with successive and preceding values respectively
After considerable debugging effort (and commenting out the debugging cat-calls):
rldat <- rle(dat$ID)
for ( nth in seq_along( rldat$lengths) ){ #cat("nth=", nth, "\n")
if(rldat$values[nth] == 0){
if (nth == 1) { # cat("first value=",rldat$values[nth+1], "\n")
dat$ID[ 1:rldat$lengths[nth] ] <-rldat$values[nth+1];
} else {
if (nth== length(rldat$lengths) ){
dat$ID[ (length(dat$ID)-rldat$lengths[nth]+1):length(dat$ID) ] <-
rldat$values[nth-1]
} else {
# cat( "seq=", (sum(rldat$lengths[1:(nth- 1)])+1): sum(rldat$lengths[1:nth]) ,"\n")
dat$ID[ (sum(rldat$lengths[1:(nth-1)])+1):sum(rldat$lengths[1:nth]) ] <-
c( rep( rldat$values[nth-1],rldat$lengths[nth]/2+.9) ,
rep( rldat$values[nth+1],rldat$lengths[nth]/2) )}}
} }

How can I select columns and rows with variable in R?

I have an object currency I would like to select one column and the rows equal to 1 with the variable Pair.
>currency
EURUSD EURUSDi USDJPY USDJPYi GBPUSD GBPUSDi AUDUSD AUDUSDi XAUUSD XAUUSDi zeroes
2000-07-16 0 0 0 0 0 1 0 0 0 0 0
2000-07-23 0 0 0 0 0 1 0 0 0 0 0
2000-07-30 0 0 0 0 0 1 0 0 0 0 0
2000-08-06 0 0 0 0 0 0 0 0 0 1 0
2000-08-13 0 1 0 0 0 0 0 0 0 0 0
From the console I can do it with subset like this :
> subset(currency$GBPUSDi, GBPUSDi == 1)
GBPUSDi
2000-07-16 1
2000-07-23 1
2000-07-30 1
2000-08-06 1
2000-08-13 1
2000-08-20 1
But as soon as it is passed in a script with variable Pair it fails. I've searched for hours in the documentation and I'm having a headache trying to figure out what is wrong.
Please find the different command I've try :
subset (currency$Pair, Pair == 1)
subset (currency, Pair = 1, select = Pair)
weights$Cur[currency$Pair = 1]
The one that works is currency[,c(Pair)] but it only select column, how can I complete with row selection of Pair = 1 ?
currency[,c(Pair)][Pair = 1] and subset (currency[,c(Pair)], Pair = 1) with = or == doesn't work.
currency$Pair[currency$Pair == 1] should work ($Pair select column Pair and [currency$Pair == 1] select values equal to 1). It looks like it don't work in your case, because currency don't contain variable Pair.
If currency is not a dataframe but matrix, you can try
currency[currency[, c("Pair")] == 1, c("Pair")]

Find # of rows between events in R

I have a series of data in the format (true/false). eg it looks like it can be generated from rbinom(n, 1, .1). I want a column that represents the # of rows since the last true. So the resulting data will look like
true/false gap
0 0
0 0
1 0
0 1
0 2
1 0
1 0
0 1
What is an efficient way to go from true/false to gap (in practice I'll this will be done on a large dataset with many different ids)
DF <- read.table(text="true/false gap
0 0
0 0
1 0
0 1
0 2
1 0
1 0
0 1", header=TRUE)
DF$gap2 <- sequence(rle(DF$true.false)$lengths) * #create a sequence for each run length
(1 - DF$true.false) * #multiply with 0 for all 1s
(cumsum(DF$true.false) != 0L) #multiply with zero for the leading zeros
# true.false gap gap2
#1 0 0 0
#2 0 0 0
#3 1 0 0
#4 0 1 1
#5 0 2 2
#6 1 0 0
#7 1 0 0
#8 0 1 1
The cumsum part might not be the most efficient for large vectors. Something like
if (DF$true.false[1] == 0) DF$gap2[seq_len(rle(DF$true.false)$lengths[1])] <- 0
might be an alternative (and of course the rle result could be stored temporarly to avoid calculating it twice).
Ok, let me put this in answer
1) No brainer method
data['gap'] = 0
for (i in 2:nrow(data)){
if data[i,'true/false'] == 0{
data[i,'gap'] = data[i-1,'gap'] + 1
}
}
2) No if check
data['gap'] = 0
for (i in 2:nrow(data)){
data[i,'gap'] = (data[i-1,'gap'] + 1) * (-(data[i,'gap'] - 1))
}
Really don't know which is faster, as both contain the same amount of reads from data, but (1) have an if statement, and I don't know how fast is it (compared to a single multiplication)

Resources