I hope I'm on the right place, because I'm lossing my mind, trying to get one quiz together.
So the thing is that I need to setup score based system for quiz. I have two sections of questions (1-13 and 14-21). Rules are:
Questions 1-13: if six or more answers are Answer 3 or Answer 4
Questions 14-21: if six or more answers are Answer 3 or Answer 4
is OPTION 1
Questions 1-13: if six or more answers are Answer 3 or Answer 4
Questions 14-21: if less than six answers are Answer 3 or Answer 4
is OPTION 2
If there are less than five answers with Answer 3 or Answer 4 in each set of questions
is OPTION 3
Now I need some system for scoring. In my program I have option for +,-,/,* between answers, but I can't come with working solution. Scores on each answer can be negative too. I'm limited with programing, because I can do only basic math expressions and not actual programming like if this, then this.
Answer 0
Answer 1
Answer 2
Answer 3
Answer 4
Question 1
0
0
0
x
x
Question 2
0
0
0
x
x
Question 3
0
0
0
x
x
Question 4
0
0
0
x
x
Question 5
0
0
0
x
x
Question 6
0
0
0
x
x
Question 7
0
0
0
x
x
Question 8
0
0
0
x
x
Question 9
0
0
0
x
x
Question 10
0
0
0
x
x
Question 11
0
0
0
x
x
Question 12
0
0
0
x
x
Question 13
0
0
0
x
x
Question 14
0
0
0
x
x
Question 15
0
0
0
x
x
Question 16
0
0
0
x
x
Question 17
0
0
0
x
x
Question 18
0
0
0
x
x
Question 19
0
0
0
x
x
Question 20
0
0
0
x
x
Question 21
0
0
0
x
x
Answers 0, 1 and 2 are not important so I placed 0 there.
Thanks in advance for any suggestions/help!
It's hard to give more advice without knowing what programming language you want to write this in and without an example.
The partial solution below should at least get you started. It is only using basic math expressions +,-,/,*, and additionally the absolute value |n| (otherwise the solution is close to impossible). Note that the for loops are just a shorthand for a chain of additions.
The caveat with this solution is that it breaks if there are exactly 6 answers 3 and 4. I can update this if you give more details as to what operators you have available.
// Assuming one correct answer
// 1 = Answer was selected, 0 = not selected
const answers = [
// Answer 3 | Answer 4
/* Q1 */[ 1 , 0 ],
/* Q2 */[ 1 , 0 ],
/* Q3 */[ 1 , 0 ],
/* Q4 */[ 0 , 1 ],
/* Q5 */[ 1 , 0 ],
/* Q6 */[ 0 , 1 ],
/* Q7 */[ 1 , 0 ],
/* Q8 */[ 1 , 0 ],
/* Q9 */[ 0 , 1 ],
/* Q10 */[ 0 , 1 ],
/* Q11 */[ 0 , 1 ],
/* Q12 */[ 1 , 0 ],
/* Q13 */[ 0 , 0 ],
/* Q14 */[ 0 , 1 ],
/* Q15 */[ 1 , 0 ],
/* Q16 */[ 0 , 0 ],
/* Q17 */[ 0 , 1 ],
/* Q18 */[ 0 , 0 ],
/* Q19 */[ 1 , 0 ],
/* Q20 */[ 1 , 0 ],
/* Q21 */[ 0 , 0 ],
];
// Calculate option
// 1. Count answers 3 or 4 in Q1-Q13
let count_1_13 = 0;
for (let i = 0; i < 13; ++i) {
count_1_13 += answers[i][0] + answers[i][1];
}
console.log(`Questions 1-13: ${count_1_13} answers 3 or 4`);
// 2. Count answers 3 or 4 in Q14-Q21
let count_14_21 = 0;
for (let i = 13; i < 21; ++i) {
count_14_21 += answers[i][0] + answers[i][1];
}
console.log(`Questions 4-21: ${count_14_21} answers 3 or 4`);
// 3. Subtract 6
// If there are 6 or more answers, the count will stay positive,
// otherwise it will become negative.
count_1_13 = count_1_13 - 6;
count_14_21 = count_14_21 - 6;
// 4. Find the weight (0 for positive, 1 for negative)
// Caveat: if there are exactly 6 answers, this breaks (division by zero)
const sign_1_13 = (1 - count_1_13 / Math.abs(count_1_13)) / 2;
const sign_14_21 = (1 - count_14_21 / Math.abs(count_14_21)) / 2;
let option = 1;
option += sign_1_13;
option += sign_14_21;
console.log(`Result: Option ${option}`);
// Arbitrary scores for each question
const scores = [
// Answer 3 | Answer 4
/* Q1 */[ 5 , 2 ],
/* Q2 */[ -2 , 9 ],
/* Q3 */[ 3 , -1 ],
/* Q4 */[ 5 , 1 ],
/* Q5 */[ 1 , 2 ],
/* Q6 */[ 5 , 1 ],
/* Q7 */[ -1 , 5 ],
/* Q8 */[ 1 , 1 ],
/* Q9 */[ 1 , 7 ],
/* Q10 */[ -6 , 3 ],
/* Q11 */[ 5 , 1 ],
/* Q12 */[ 6 , 7 ],
/* Q13 */[ 5 , -4 ],
/* Q14 */[ 7 , 3 ],
/* Q15 */[ -1 , -2 ],
/* Q16 */[ 1 , 1 ],
/* Q17 */[ 5 , 5 ],
/* Q18 */[ 1 , 1 ],
/* Q19 */[ 2 , 6 ],
/* Q20 */[ 2 , -4 ],
/* Q21 */[ 4 , 8 ],
];
// Calculate score
let totalScore = 0;
for (let i = 0; i < scores.length; ++i) {
totalScore += scores[i][0] * answers[i][0] + scores[i][1] * answers[i][1];
}
console.log(`Total score: ${totalScore}`);
Related
I am working on panel data that looks like this:
d <- data.frame(id = c("a", "a", "a", "a", "a", "b", "b", "b", "b", "b", "c", "c", "c", "c", "c"),
time = c(1, 2, 3, 4, 5, 1, 2, 3, 4, 5, 1, 2, 3, 4, 5),
iz = c(0,1, 1, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 1, 1))
id time iz
1 a 1 0
2 a 2 1
3 a 3 1
4 a 4 0
5 a 5 0
6 b 1 0
7 b 2 0
8 b 3 0
9 b 4 0
10 b 5 1
11 c 1 0
12 c 2 0
13 c 3 0
14 c 4 1
15 c 5 1
Here iz is an indicator for an event or a treatment (iz = 1). What I need is a variable that counts the periods before and after an event or the distance to and from an event. This variable would look like this:
id time iz nvar
1 a 1 0 -1
2 a 2 1 0
3 a 3 1 0
4 a 4 0 1
5 a 5 0 2
6 b 1 0 -4
7 b 2 0 -3
8 b 3 0 -2
9 b 4 0 -1
10 b 5 1 0
11 c 1 0 -1
12 c 2 0 -2
13 c 3 0 -3
14 c 4 1 0
15 c 5 1 0
I have tried working with the answers given here and here but can't make it work in my case.
I would really appreciate any ideas how to approach this problem. Thank you in advance for all ideas and suggestions.
1) rleid This code applies rleid from data.table to each id and then generates a negative reverse sequence if that produces a run of 1's and a forward sequence otherwise, i.e. we assume that a forward positive sequence should be used except before the first run of ones. For the 1's in iz zero that out. There can be any number of runs in an id and it also supports id's with only 0's or only 1's. It assumes that time has no gaps.
library(data.table)
Seq <- function(x, s = seq_along(x)) if (x[1] == 1) -rev(s) else s
nvar <- function(iz, r = rleid(iz)) ave((1-iz) * r, r, FUN = Seq)
transform(d, nvar = (1-iz) * ave(iz, id, FUN = nvar))
giving:
id time iz nvar
1 a 1 0 -1
2 a 2 1 0
3 a 3 1 0
4 a 4 0 1
5 a 5 0 2
6 b 1 0 -4
7 b 2 0 -3
8 b 3 0 -2
9 b 4 0 -1
10 b 5 1 0
11 c 1 0 -3
12 c 2 0 -2
13 c 3 0 -1
14 c 4 1 0
15 c 5 1 0
2) base This code uses only base R. It assumes that every id has at most one run of ones. There is no restriction on whether there are any zeros. Also it supports gaps in time. It applies nvar to the row numbers of each id. First it calculates the range rng of the times of the ones and then calculates the signed distance in the last line of nvar. The output is identical to that shown in (1). If we could assume that every id has exactly one run of 1's the if statement could be omitted.
nvar <- function(ix) with(d[ix, ], {
if (all(iz == 0)) return(iz)
rng <- range(time[iz == 1])
(time < rng[1]) * (time - rng[1]) + (time > rng[2]) * (time - rng[2])
})
transform(d, nvar = ave(1:nrow(d), id, FUN = nvar))
2a) This variation of (2) passes time and iz to nvar by encoding them as the real and imaginary parts of a complex vector in order to avoid having to deal with row numbers but it is otherwise the same as (2). We have omitted the if statement in (2) but it could be added back in if any id's have no ones.
nvar <- function(x, time = Re(x), iz = Im(x), rng = range(time[iz == 1]))
(time < rng[1]) * (time - rng[1]) + (time > rng[2]) * (time - rng[2])
transform(d, nvar = Re(ave(time + iz * 1i, id, FUN = nvar)))
Here is a solution that is a (tiny) bit more complex than the one from G.Grothendieck. But is will be able to handle non-sequential times.
library( data.table )
#make d a data.table
setDT(d)
#you can remove the trailing [], they are just for passing the output to the console...
#nvar = 0 where iz = 1
d[ iz == 1, nvar := 0 ][]
#calculate nvar for iz == 0 BEFORE iz == 1, using a forward rolling join
#create subsets for redability
d1 <- d[ iz == 1, ]
d0 <- d[ iz == 0, ]
d[ iz == 0, nvar := time - d1[ d0, x.time, on = .(id, time), roll = -Inf ] ][]
#calculate nvar for iz == 0 AFTER iz == 1, usning a backward rolling join
#create subsets for redability
d1 <- d[ iz == 1, ]
d0 <- d[ iz == 0 & is.na( nvar ), ]
d[ iz == 0 & is.na(nvar) , nvar := time - d1[ d0, x.time, on = .(id, time), roll = Inf ] ][]
# id time iz nvar
# 1: a 1 0 -1
# 2: a 2 1 0
# 3: a 3 1 0
# 4: a 4 0 1
# 5: a 5 0 2
# 6: b 1 0 -4
# 7: b 2 0 -3
# 8: b 3 0 -2
# 9: b 4 0 -1
# 10: b 5 1 0
# 11: c 1 0 -3
# 12: c 2 0 -2
# 13: c 3 0 -1
# 14: c 4 1 0
# 15: c 5 1 0
One dplyr and purrr option could be:
d %>%
group_by(id) %>%
mutate(nvar = map_dbl(.x = seq_along(iz), ~ min(abs(.x - which(iz == 1)))),
nvar = if_else(cumsum(iz) == 0, -nvar, nvar))
id time iz nvar
<fct> <dbl> <dbl> <dbl>
1 a 1 0 -1
2 a 2 1 0
3 a 3 1 0
4 a 4 0 1
5 a 5 0 2
6 b 1 0 -4
7 b 2 0 -3
8 b 3 0 -2
9 b 4 0 -1
10 b 5 1 0
11 c 1 0 -3
12 c 2 0 -2
13 c 3 0 -1
14 c 4 1 0
15 c 5 1 0
Suppose I have this data:
x = c(14,14, 6, 7 ,14 , 0 ,0 ,0 , 0, 0, 0 , 0 , 0, 0 , 0 , 0 , 0, 9 ,1 , 3 ,8 ,9 ,15, 9 , 8, 13, 8, 4 , 6 , 7 ,10 ,13, 3,
0 , 0 , 0 , 0 , 0 , 0, 0, 0 , 0 , 0 , 0, 0, 0, 0, 0 ,0, 0 , 0 , 0, 0, 0, 0, 0 , 0, 0, 4 , 7 ,4, 5 ,16 , 5 ,5 , 9 , 4 ,4, 9 , 8, 2, 0 ,0 ,0 ,0 ,0, 0, 0, 0 ,0 , 0, 0, 0, 0, 0, 0, 0, 0,0)
x
[1] 14 14 6 7 14 0 0 0 0 0 0 0 0 0 0 0 0 9 1 3 8 9 15 9 8
[26] 13 8 4 6 7 10 13 3 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
[51] 0 0 0 0 0 0 0 0 4 7 4 5 16 5 5 9 4 4 9 8 2 0 0 0 0
[76] 0 0 0 0 0 0 0 0 0 0 0 0 0 0
I want to recover the indices beginning where there are more than 3 zeroes in a row and terminating with the last 0 before a nonzero.
For example,
I would get
6, 17 for the first rash of zeroes, etc.
Here are two base R approaches:
1) rle First run rle and then compute ok to pick out the sequences of zeros that are more than 3 long. We then compute the starts and ends of all repeated sequences subsetting to the ok ones at the end.
with(rle(x), {
ok <- values == 0 & lengths > 3
ends <- cumsum(lengths)
starts <- ends - lengths + 1
data.frame(starts, ends)[ok, ]
})
giving:
starts ends
1 6 17
2 34 58
3 72 89
2) gregexpr Take the sign of each number -- that will be 0 or 1 and then concatenate those into a long string. Then use gregexpr to find the location of at least 4 zeros. The result gives the starts and the ends can be computed from that plus the match.length attribute minus 1.
s <- paste(sign(x), collapse = "")
g <- gregexpr("0{4,}", s)[[1]]
data.frame(starts = 0, ends = attr(g, "match.length") - 1) + g
giving:
starts ends
1 6 17
2 34 58
3 72 89
Starts = which(diff(x == 0) == 1) + 1
Ends = which(diff(x == 0) == -1)
if(length(Ends) < length(Starts)) {
Ends = c(Ends, length(x)) }
Starts
[1] 6 34 72
Ends
[1] 17 58 89
This works for your test data, but allows any sequence of zeros, including short ones. To insure that you get sequences of length at least n, add:
n=3
Long = which((Ends - Starts) >= n)
Starts = Starts[Long]
Ends = Ends[Long]
By using dplyr , get the diff then if the diff not equal to 0 , they are not belong to same group , after cumsum we get the grouid
library(dplyr)
df=data.frame('x'=x,rownumber=seq(length(x)))
df$Groupid=cumsum(c(0,diff(df$x==0))!=0)
df%>%group_by(Groupid)%>%summarize(start=first(rownumber),end=last(rownumber),number=first(x),size=n())%>%filter(number==0&size>=3)
# A tibble: 3 x 5
Groupid start end number size
<int> <int> <int> <dbl> <int>
1 1 6 17 0 12
2 3 34 58 0 25
3 5 72 89 0 18
If x happens to be a column of a data.table you can do
library(data.table)
dt <- data.table(x = x)
dt[, if(.N > 3 & all(x == 0)) .(starts = first(.I), ends = last(.I))
, by = rleid(x)]
# rleid starts ends
# 1: 5 6 17
# 2: 22 34 58
# 3: 34 72 89
Explanation:
rleid(x) gives an ID (integer) for each element in x indicating
which "run" the element is a member of, where "run" means a sequence
of adjacent equal values.
dt[, <code>, by = rle(x)] partitions dt according to rleid(x) and computes <code> for each subset of dt's rows. The results are stacked together in a single data.table.
.N is the number of elements in the given subset
.I is the vector of row numbers corresponding to the subset
first and last give the first and last element of a vector
.(<stuff>) is the same as list(<stuff>)
The rleid function, by grouping within the brackets, .N and .I symbols, first and last functions are part of the data.table package.
I have a dataframe (.txt) which looks like this [where "dayX" = the day of death in a survival assay in fruitflies, the numbers beneath are the number of flies to die in that treatment combination on that day, X or A are treaments, m & f are also treatments, the first number is the line, the second number is the block]
line day1 day2 day3 day4 day5
1 Xm1.1 0 0 0 2 0
2 Xm1.2 0 0 1 0 0
3 Xm2.1 1 1 0 0 0
4 Xm2.2 0 0 0 3 1
5 Xf1.1 0 3 0 0 1
6 Xf1.2 0 0 1 0 0
7 Xf2.1 2 0 2 0 0
8 Xf2.2 1 0 1 0 0
9 Am1.1 0 0 0 0 2
10 Am1.2 0 0 1 0 0
11 Am2.1 0 2 0 0 1
12 Am2.2 0 2 0 0 0
13 Af1.1 3 0 0 1 0
14 Af1.2 0 1 3 0 0
15 Af1.1 0 0 0 1 0
16 Af2.2 1 0 0 0 0
and want it to become this using R->
XA mf line block individual age
1 X m 1 1 1 4
2 X m 1 1 2 4
3 X m 1 2 1 3
and so on...
the resulting dataframe collects the "age" value from the day the individual died, as scored in the upper dataframe, for example there were two flies that died on the 4th day (day4) in treatment Xm1.1 therefore R creates two rows, one containing information extracted regarding the first individual and thus being labelled as individual "1", then another row with the same information except labelled as individual "2".. if a 3rd individual died in the same treatment on day 5, there would be a third row which is the same as the above two rows except the "age" would be "5" and individual would be "3". When it moves on to the next treatment row, in this case Xm1.2, the first individual to die within that treatment set would be labelled as individual "1" (which in this case dies on day 3). In my example there is a total of 38 deaths, therefore I am trying to get R to build a df which is 38*6 (excl. headers).
is there a way to take my dataframe [the real version is approx 50*640 with approx 50 individuals per unique combination of X/A, m/f, line (1:40), block (1-4) so ~32000 individual deaths] to an end dataframe of 6*~32000 in an automated way?
both of these example dataframes can be built using this code if it helps you to try out solutions:
test<-data.frame(1:16);colnames(test)=("line")
test$line=c("Xm1.1","Xm1.2","Xm2.1","Xm2.2","Xf1.1","Xf1.2","Xf2.1","Xf2.2","Am1.1","Am1.2","Am2.1","Am2.2","Af1.1","Af1.2","Af2.1","Af2.2")
test$day1=rep(0,16);test$day2=rep(0,16);test$day3=rep(0,16);test$day4=rep(0,16);test$day5=rep(0,16)
test$day4[1]=2;test$day3[2]=1;test$day2[3]=1;test$day4[4]=3;test$day5[5]=1;
test$day3[6]=1;test$day1[7]=2;test$day1[8]=1;test$day5[9]=3;test$day3[10]=1;
test$day2[11]=2;test$day2[12]=2;test$day4[13]=1;test$day3[14]=3;test$day4[15]=1;
test$day1[16]=1;test$day3[7]=2;test$day3[8]=1;test$day2[5]=3;test$day1[3]=1;
test$day5[11]=1;test$day5[9]=2;test$day5[4]=1;test$day1[13]=3;test$day2[14]=1;
test2=data.frame(rep(1:3),rep(1:3),rep(1:3),rep(1:3),rep(1:3),rep(1:3))
colnames(test2)=c("XA","mf","line","block","individual","age")
test2$XA[1]="X";test2$mf[1]="m";test2$line[1]=1;test2$block[1]=1;test2$individual[1]=1;test2$age[1]=4;
test2$XA[2]="X";test2$mf[2]="m";test2$line[2]=1;test2$block[2]=1;test2$individual[2]=2;test2$age[2]=4;
test2$XA[3]="X";test2$mf[3]="m";test2$line[3]=1;test2$block[3]=2;test2$individual[3]=1;test2$age[3]=3;
apologies for the awfully long way of making this dummy dataset, suffering from sleep deprivation and jetlag and haven't used R for months, if you run the code in R you will hopefully see better what I aim to do
-------------------------------------------------------------------------------------
By Rg255:
Currently stuck at this derived from #Arun's answer (I have added the strsplit (as.character(dt$line) , "" )) section to get around one error)
df=read.table("C:\\Users\\...\\data.txt",header=T)
require(data.table)
head(df[1:20])
dt <- as.data.table(df)
dt <- dt[, {dd <- unlist(.SD, use.names = FALSE);
list(individual = sequence(dd[dd>0]),
age = rep(which(dd>0), dd[dd>0])
)}, by=line]
out <- as.data.table(data.frame(do.call(rbind, strsplit(as.character(dt$line), ""))[, c(1:3,5)], stringsAsFactors=FALSE))
setnames(out, c("XA", "mf", "line", "block"))
out[, `:=`(line = as.numeric(line), block = as.numeric(block))]
out <- cbind(out, dt[, list(individual, age)])
Produces the following output:
> df=read.table("C:\\Users\\..\\data.txt",header=T)
> require(data.table)
> head(df[1:20])
line Day4 Day6 Day8 Day10 Day12 Day14 Day16 Day18 Day20 Day22 Day24 Day26 Day28 Day30 Day32 Day34 Day36 Day38 Day40
1 Xm1.1 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 1 4 2
2 Xm2.1 0 0 0 0 0 0 0 0 0 2 0 0 0 1 2 1 0 2 0
3 Xm3.1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 2 1
4 Xm4.1 0 0 0 0 0 0 0 0 0 0 0 0 1 1 0 1 2 3 8
5 Xm5.1 0 0 0 0 0 0 0 0 0 0 0 0 0 2 2 3 3 3 6
6 Xm6.1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1
> dt <- as.data.table(df)
> dt <- dt[, {dd <- unlist(.SD, use.names = FALSE);
+ list(individual = sequence(dd[dd>0]),
+ age = rep(which(dd>0), dd[dd>0])
+ )}, by=line]
> out <- as.data.table(data.frame(do.call(rbind, strsplit(as.character(dt$line), ""))[, c(1:3,5)], stringsAsFactors=FALSE))
Warning message:
In function (..., deparse.level = 1) :
number of columns of result is not a multiple of vector length (arg 1)
> setnames(out, c("XA", "mf", "line", "block"))
> out[, `:=`(line = as.numeric(line), block = as.numeric(block))]
Error in `[.data.table`(out, , `:=`(line = as.numeric(line), block = as.numeric(block))) :
LHS of := must be a single column name, when with=TRUE. When with=FALSE the LHS may be a vector of column names or positions.
In addition: Warning message:
In eval(expr, envir, enclos) : NAs introduced by coercion
> out <- cbind(out, dt[, list(individual, age)])
>
Here goes a data.table solution. The line column must have unique values.
require(data.table)
df <- read.table("data.txt", header=TRUE, stringsAsFactors=FALSE)
dt <- as.data.table(df)
dt <- dt[, {dd <- unlist(.SD, use.names = FALSE);
list(individual = sequence(dd[dd>0]),
age = rep(which(dd>0), dd[dd>0])
)}, by=line]
out <- as.data.table(data.frame(do.call(rbind,
strsplit(gsub("([[:alpha:]])([[:alpha:]])([0-9]+)\\.([0-9]+)$",
"\\1 \\2 \\3 \\4", dt$line), " ")), stringsAsFactors=FALSE))
setnames(out, c("XA", "mf", "line", "block"))
out[, `:=`(line = as.numeric(line), block = as.numeric(block))]
out <- cbind(out, dt[, list(individual, age)])
This works on your data.txt file.
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 ;-)
I am working on a project and I reached this point but in fact I am stuck on it since one week ago, I tried many ideas but all trials to code my algorithm failed.
Suppose we have the following simple graph:
the edges in order are: 1--3, 1--4, 3--2
For each edge, a random walk is defined on each vertex to move to one of it's neighbors like:
For the first edge, v1=1 ,v2=3, n1=3,4 and n2=1,2 in order, so the possible moves from v1 and v2 are:
1 to 3,3 to 1
1 to 4,3 to 1
1 to 3,3 to 2
1 to 4,3 to 2
For the second edge, v1=1 ,v2=4, n1=3,4 and n2=1 in order,so the possible moves from v1 and v2 are:
1 to 3,4 to 1
1 to 4,3 to 1
For the third edge, v1=3 ,v2=2, n1=1,2 and n2=3 in order,so the possible moves from v1 and v2 are:
3 to 1,2 to 3
3 to 2,2 to 3
For the whole graph there are just 8 possible moves so I have 8 variables to construct the constraints matrix
Let us denote the moves by x's (according to their order of occurrences); i.e
(1 to 3,3 to 1) to be represented by x_1
(1 to 4,3 to 1) to be represented by x_2
:
(3 to 1,2 to 3) to be represented by x_7
(3 to 2,2 to 3) to be represented by x_8
I want to build the required constraints matrix depending on these moves, the number of constraints will equal \sum{i} ( number of neighbors for v1(i) * number of neighbors for v2(i) ) which is 10 in our graph.
My algorithm to build this matrix is:
Step1: 1) select 1st edge, fix v1, v2, n2
2) change n1 and fill the 1st row of the matrix by 1's in the place of the resulted moves and 0 if there is no similar move on the graph until you finish all elements in n1.
Step2: move to the 2nd row of the matrix and select the 2nd element of n2 and
1) loop over n1
2) fill the 2nd row by 1's in the place of the resulted moves until you finish all elements in n1.
Step3: since you selected all elements in n1 and n2 for the vertices in the first edge move to a new row in the matrix
Step4: Select next edges and do the same work done before until you finish all edges.
Step5: select the 1st edge again and do the same work but while fixing v1,v2 &n1, loop over n2
The resulted matrix according to this algorithm will be:
1 1 0 0 0 0 0 0
0 0 1 1 0 0 0 0
0 0 0 0 1 1 0 0
0 0 0 0 0 0 1 1
1 0 1 0 0 0 0 0
0 1 0 1 0 0 0 0
0 0 0 0 1 0 0 0
0 0 0 0 0 1 0 0
0 0 0 0 0 0 1 0
0 0 0 0 0 0 0 1
What I failed to do is: how to let the matrix know that there is a move and to replace it by 1 in it's position and if there is no move to replace it by 0 in it's position
My code is:
library(igraph)
graph<-matrix(c(1,3,1,4,3,2),ncol=2,byrow=TRUE)
g<-graph.data.frame(d = graph, directed = FALSE)
countercol<-0
for (edge in 1:length(E(g))){
v1<-ends(graph = g, es = edge)[1]
v2<-ends(graph = g, es = edge)[2]
n1<-neighbors(g,v1,mode=c("all"))
n2<-neighbors(g,v2,mode=c("all"))
countercol=countercol+(length(n1)*length(n2))
}
counterrow<-0
for (edge in 1:length(E(g))){
v1<-ends(graph = g, es = edge)[1]
v2<-ends(graph = g, es = edge)[2]
n1<-neighbors(g,v1,mode=c("all"))
n2<-neighbors(g,v2,mode=c("all"))
counterrow=counterrow+(length(n1)+length(n2))
}
for (edge in 1:length(E(df))){
v1<-ends(graph = df, es = edge)[1]
v2<-ends(graph = df, es = edge)[2]
n1<-neighbors(df,v1,mode=c("all"))
n2<-neighbors(df,v2,mode=c("all"))
...
...
...
}
I am not looking for someone to write the code, what I want is the idea to let the program differentiate between the possible moves and store 1's and 0's in the suitable position for the resulted move.
Many Many thanks for any kind of help
Here's a solution consisting of two parts
edgeMoves <- function(e) {
umoves <- sapply(ends(graph = g, es = e), neighbors, graph = g, mode = "all", simplify = FALSE)
do.call(paste, c(expand.grid(mapply(function(x, y)
paste(x, names(y), sep =" to "), ends(graph = g, es = e), umoves, SIMPLIFY = FALSE)), sep = ", "))
}
edgeConstraints <- function(e) {
v <- ends(graph = g, es = e)
n1 <- names(neighbors(g, v[1], mode = "all"))
n2 <- names(neighbors(g, v[2], mode = "all"))
t(cbind(sapply(n2, function(nn2) moves %in% paste0(v[1], " to ", n1, ", ", v[2], " to ", nn2)),
sapply(n1, function(nn1) moves %in% paste0(v[1], " to ", nn1, ", ", v[2], " to ", n2))))
}
moves <- do.call(c, sapply(E(g), edgeMoves))
moves
# [1] "1 to 3, 3 to 1" "1 to 4, 3 to 1" "1 to 3, 3 to 2"
# [4] "1 to 4, 3 to 2" "1 to 3, 4 to 1" "1 to 4, 4 to 1"
# [7] "3 to 1, 2 to 3" "3 to 2, 2 to 3"
do.call(rbind, sapply(E(g), edgeConstraints)) * 1
# [,1] [,2] [,3] [,4] [,5] [,6] [,7] [,8]
# 1 1 1 0 0 0 0 0 0
# 2 0 0 1 1 0 0 0 0
# 3 1 0 1 0 0 0 0 0
# 4 0 1 0 1 0 0 0 0
# 1 0 0 0 0 1 1 0 0
# 3 0 0 0 0 1 0 0 0
# 4 0 0 0 0 0 1 0 0
# 3 0 0 0 0 0 0 1 1
# 1 0 0 0 0 0 0 1 0
# 2 0 0 0 0 0 0 0 1
The row order is different, but I suspect that it is not a problem. Also, for a single edge you may use edgeMoves(e) and edgeConstraints(e) * 1.