Finding the inversion of an easier function is simple. The way I find the way of doing this by flipping the x and the y in the equation and solving for y. But I am stuck on a certain part.
y = (6*x) mod 13
x = (6*y) mod 13
The inverse of that function will only be defined for values between 0 and 12. Also for every possible y (in between 0 and 12) there will be an infinite number of possible x that fulfill the equation.
Let's try to solve for y
x = (6*y) mod 13
x + n*13 = (6*y)
y = (x + n*13)/6 | x ∈ {0,…,12}, n ∈ ℕ
where n is an unknown positive integer that could have any arbitrary value
To compute the inverse of y = 6 * x mod 13, I am first going to solve for x and replace x with y (and vice versa) later.
Since y = 6 * x mod 13, x = 6^(-1) * y mod 13, where 6^(-1) is the modular multiplicative inverse of 6 for the modulus 13. Your task now becomes finding 6^(-1) mod 13. In other words, you have to find m such that 6 * m = 1 mod 13.
Note that 6 * 2 = 12 = -1 mod 13. Squaring both sides, 6 * 6 * 2 * 2 = 1 mod 13, or 6 * 24 = 1 mod 13. Since 24 = 11 mod 13, therefore 6 * 11 = 1 mod 13 and 11 = 6^(-1) mod 13.
Thus, our equation for x now becomes x = 11 * y mod 13. Replacing y -> x and x -> y, the inverse of the given function is given by y = 11 * x mod 13.
This nifty Python script can be used to test the validity of our result:
def f(x):
return (6 * x) % 13
def f_inv(x):
return (11 * x) % 13
for x in range(13):
print x, f_inv(f(x)), x == f_inv(f(x))
When run, it gives the following output:
0 0 True
1 1 True
2 2 True
3 3 True
4 4 True
5 5 True
6 6 True
7 7 True
8 8 True
9 9 True
10 10 True
11 11 True
12 12 True
Thus validating the premise that f^(-1)(x) = 11 * x mod 13 satisfies the required premise that f^(-1)(f(x)) = x.
Related
I would like R to count every time an X or Y value in a data set is within 10 numbers of each other. My dataset appears like this:
Point 1: X: 30, Y: 34
Point 2: X 35, Y: 30
Point 3: X 10, Y: 10
d <- data.frame(
X = c(30, 35, 10),
Y = c(34, 30, 10)
)
d
#> X Y
#> 1 30 34
#> 2 35 30
#> 3 10 10
I would like R to count Point 1 and 2 being next to each other.
This is what I have so far:
def distance
count = length of data set
nested for loop
for d in data
for p in list
if distance(d[0], d[1], p[0], p[1]) ==0:
continue
Élif distance < 12 and distance != 0:
count -= 1
To see if two values are within some tolerance you can use the absolute value of their difference, which in R is
abs(a - b) <= tolerance
The lag() function returns the lagged value (some number of indices prior) so you can use that to see if a value is within some value of the previous one. You can calculate this for your two columns
d$x_within_10 <- abs(lag(d$X) - d$X) <= 10
d$y_within_10 <- abs(lag(d$Y) - d$Y) <= 10
d
#> X Y x_within_10 y_within_10
#> 1 30 34 NA NA
#> 2 35 30 TRUE TRUE
#> 3 10 10 FALSE FALSE
The first row has nothing previous to compare to so that result is NA.
I am trying to make a piece-wise function. This is a really basic one. I want y to be a list of values (preferably not just a list of integers but a list of real numbers like (1.34, 20.92) in the future).
How might I make a piece-wise function?
y <- 1:10
if (y < 2){
print("CAN'T COMPUTE")
} else if (y >= 2 & y < 6){
print(y^2)
} else {
print(y * 2)
}
Let me give it a try:
library("dplyr")
y <- 1:10
y %>%
as_tibble() %>%
mutate(res = case_when(y < 2 ~ "CAN'T COMPUTE",
y >= 2 & y < 6 ~ as.character(y^2),
TRUE ~ as.character(y*2)))
Here's the results:
# A tibble: 10 x 2
value res
<int> <chr>
1 1 CAN'T COMPUTE
2 2 4
3 3 9
4 4 16
5 5 25
6 6 12
7 7 14
8 8 16
9 9 18
10 10 20
Here are a some base R approaches. We have used NA instead of a character string in order to produce a numeric vector result. The first uses a nested ifelse. The second uses a single ifelse to select between NA and the other values and computes the other values using a formula. The third computes which leg of the result is wanted (1, 2 or 3) and then uses switch to select that leg. The fourth is a variation of three that uses findInterval to compute the leg number.
ifelse(y < 2, NA, ifelse(y < 6, y^2, 2*y))
## [1] NA 4 9 16 25 12 14 16 18 20
ifelse(y < 2, NA, (y < 6) * y^2 + (y >= 6) * 2*y)
## [1] NA 4 9 16 25 12 14 16 18 20
mapply(switch, 1 + (y >= 2) + (y >= 6), NA, y^2, 2*y)
## [1] NA 4 9 16 25 12 14 16 18 20
mapply(switch, findInterval(y, c(-Inf, 2, 6, Inf), left.open = FALSE), NA, y^2, 2*y)
## [1] NA 4 9 16 25 12 14 16 18 20
I have a data.table as follows
set.seed(5)
x <- data.table(x=sample(1:20,15))
> x
x
1: 5
2: 14
3: 17
4: 20
5: 2
6: 11
7: 8
8: 15
9: 12
10: 16
11: 3
12: 18
13: 10
14: 4
15: 13
and I would like to start at 1 and cumulate values iteratively such that the value of cumsum() determines the next number to be added to the sum.
In the example I want to add the first value of x, here 5, then jump to value number 5 and add that, here 2, then jump to value number 5+2=7, here 8, then value number 5+2+8=15, here 13.
That is, I want to get a vector
> res
[1] 1 5 7 15
Has anyone any idea for this problem?
We can use Reduce with accumulate = TRUE
accum <- Reduce(function(i, j) i + x$x[i], x$x, accumulate = TRUE)
c(1, accum[!is.na(accum)])
# [1] 1 5 7 15 28
or purrr::accumulate
library(purrr)
accum <- accumulate(x$x, ~ .x + x$x[.x])
c(1, accum[!is.na(accum)])
# [1] 1 5 7 15 28
A base R solution:
i = 1
v = i
sum = 0
while (i <= nrow(x)) {
v = c(v, i)
sum = sum + x$x[i]
i = sum
}
Here's a function that takes how long you want your vector to be and produces a vector of that length:
recursiveadd<-function(x, n) {k<-x$x[1]
for (i in 1:(n-1)) {
k[i+1]<-sum(x$x[k[i]],k[i])
}
k
}
recursiveadd(x,4)
[1] 5 7 15 28
I have a vector like this
seq_vector <- c(3,12,5,9,11,8,4,6,7,11,15,3,9,10,12,2)
I want to format them in descending order of odd numbers, followed by ascending order of even numbers. Output of above seq_vector will be
new_seq_vector <- c(15,11,11,9,9,7,5,3,3,2,4,6,8,10,12,12)
Can you please help me with the logic of the same?
Try x[order(x*v)] where v is -1 for odd, +1 for even.
Thanks to #lmo for this:
x[order( x*(-1)^x )]
# [1] 15 11 11 9 9 7 5 3 3 2 4 6 8 10 12 12
So v = (-1)^x here.
Some other ways to build v: #d.b's (-1)^(x %% 2); and mine, 1-2*(x %% 2).
(Thanks #d.b) If x contains negative integers, an additional sorting vector is needed:
# new example
x = c(2, 5, -15, -10, 1, -3, 12)
x[order(v <- (-1)^x, x*v)]
# [1] 5 1 -3 -15 -10 2 12
Take modulus by 2 (%% 2) to determine the odd and even elements and sort accordingly.
c(sort(seq_vector[seq_vector %% 2 == 1], decreasing = TRUE), #For odd
sort(seq_vector[seq_vector %% 2 == 0])) #For even
#[1] 15 11 11 9 9 7 5 3 3 2 4 6 8 10 12 12
Use an auxiliary function.
is.odd <- function(x) (x %% 2) == 1
result <- c(sort(seq_vector[is.odd(seq_vector)], decreasing = TRUE),
sort(seq_vector[!is.odd(seq_vector)]))
result
I called the table() function on a data.frame.
This is the output.
Browse[1]> x
II III IV [Unknown] V
1 9 10 3 1
Browse[1]> y
I III IV [Unknown] V
3 12 15 10 2
The problem is that one of the columns is not shown because there are 0 elements there. Thus, when I plot this table on a barplot, nothing is shown for that column. How can I add a specific column with the number 0 to it?
In your case, table() returns a named vector. I can construct it by:
x <- c(II = 1, III = 9, IV = 10, "[Unknown]" = 9, V = 1)
# II III IV [Unknown] V
# 1 9 10 9 1
A named vector is still a vector, where you only have elements not columns. We can use c() to concatenate:
x <- c(I = 0, x)
# I II III IV [Unknown] V
# 0 1 9 10 9 1
Generally, we can use append(). For example, with your y:
y <- c(I = 3, III = 12, IV = 15, "[Unknown]" = 10, V = 2)
# I III IV [Unknown] V
# 3 12 15 10 2
We can do:
y <- append(y, 0, 1) ## insert value 0 after y[1]
# I III IV [Unknown] V
# 3 0 12 15 10 2
But we have to set names via a separate step:
names(y)[2] <- "II"
# I II III IV [Unknown] V
# 3 0 12 15 10 2
Edit
Thanks to #thelatemail, for your y we could simple do:
append(y, c(II = 0), 1)
# I II III IV [Unknown] V
# 3 0 12 15 10 2