2017-07-26 1 views
1

que je cherchais depuis un certain temps, mais il semble la réponse semble toujours être à utiliser eval(parse(text="1+1")).Comment calculer « 1 + 1 » sans utiliser eval (parse (...?

J'ai une colonne dans mon cadre de données, il a une liste de chaînes telles que "1 + 1 * 6", "1 * 4/3" etc. Je souhaite les calculer dans une nouvelle colonne sans utiliser les fonctions eval(parse( que je cherche à faire il plus de 8 millions de lignes

il est fondamentalement une tentative de répondre à la question:. Compte tenu des chiffres 1:9 trouver toutes les solutions où (A_B_C)/(D_E_F) = GHI, où A:I sont les numéros 1:9 (sans répéter) et e Les underscores sont l'un des quatre opérateurs *, /, +,-, également sans répétition.

J'ai créé une base de données avec toutes les permutations de 1:9 et pour chacun de ceux-ci j'ai calculé les permutations des quatre opérateurs.

require(gtools) 
x <- permutations(n = 9, r = 9, v = 1:9) 
y <- permutations(n = 4, r = 4, v = c("*", "/", "+", "-")) 

for(i in 1:nrow(x)){ 
    for(j in 1:nrow(y)){ 
    math <- paste("(", x[i,1], y[j,1], x[i,2],y[j,2], x[i,3],")", "/", "(", x[i,4] ,y[j,3], x[i,5] ,y[j,4], x[i,6],")") 
    equals <- eval(parse(text=math)) 
    sum <- as.numeric(paste0(x[i,7], x[i,8], x[i,9])) 
    if(sum==equals) { 
     print(c(i,j)) 
    } 
    } 
} 

Cependant, cela prend beaucoup trop de temps, d'où je suis en train de supprimer le temps eval(parse(..

Toute aide serait vraiment apprécié. Merci!

Freddie

+0

S'il vous plaît mettre à jour votre question et de le rendre plus facile à lire. –

+0

Conservez tous les numéros dans la colonne 9, puis jouez avec quelque chose comme ceci "+ (2, 3)". Impossible de formater correctement, envelopper le signe + avec backtics. – zx8754

+0

Je suis d'accord avec @ zx8754, vous êtes fondamentalement deparsing lorsque vous construisez vos chaînes. Évitez cela et il n'y a pas besoin d'analyser. Si vous voulez plus d'aide, vous devriez créer un exemple plus petit. L'exécution de votre code prend trop de temps. – Roland

Répondre

1

Vectorisation est la clé

math <- apply(
    y, 
    1, 
    function(j){ 
    paste("(", x[, 1], j[1], x[, 2], j[2], x[, 3],")/(", x[, 4], j[3], x[, 5], j[4], x[, 6], ")") 
    } 
) 
math <- apply(math, 2, paste, collapse = ",") 
math <- paste("c(", math, ")") 
equals <- sapply(parse(text = math), eval) 
sum <-matrix(x[, 7] * 100 + x[, 8] * 10 + x[, 9], nrow = nrow(x), ncol = nrow(y)) 
abs(sum - equals) < 1e-8 

Voyons voir ce que la différence de vitesse est

exigent (gtools) x < - permutations (n ​​= 9, r = 9, v = 1: 9) y < - permutations (n ​​= 4, r = 4, v = c ("*", "/", "+", "-"))

x <- x[sample(nrow(x), 40), ] 
y <- y[sample(nrow(y), 20), ] 

library(microbenchmark) 
microbenchmark(
    loop = for(i in 1:nrow(x)){ 
    for(j in 1:nrow(y)){ 
     math <- paste("(", x[i,1], y[j,1], x[i,2],y[j,2], x[i,3],")", "/", "(", x[i,4] ,y[j,3], x[i,5] ,y[j,4], x[i,6],")") 
     equals <- eval(parse(text=math)) 
     sum <- as.numeric(paste0(x[i,7], x[i,8], x[i,9])) 
     if(sum==equals) { 
     print(c(i,j)) 
     } 
    } 
    }, 
    vectorised = { 
    math <- apply(
     y, 
     1, 
     function(j){ 
     paste("(", x[, 1], j[1], x[, 2], j[2], x[, 3],")/(", x[, 4], j[3], x[, 5], j[4], x[, 6], ")") 
     } 
    ) 
    math <- apply(math, 2, paste, collapse = ",") 
    math <- paste("c(", math, ")") 
    equals <- sapply(parse(text = math), eval) 
    sum <-matrix(x[, 7] * 100 + x[, 8] * 10 + x[, 9], nrow = nrow(x), ncol = nrow(y)) 
    abs(sum - equals) < 1e-8 
    } 
) 

Les résultats:

Unit: milliseconds 
     expr  min   lq  mean  median   uq  max neval cld 
     loop 158.666383 162.084918 167.477490 165.880665 170.258076 240.43746 100 b 
vectorised 8.540623 8.966214 9.613615 9.142515 9.413117 17.88282 100 a 
+0

Bonjour Thierry, Merci pour votre commentaire. J'ai essayé d'exécuter votre code vectorisé 'equals <- sapply (analyse (texte = math), eval)' mais j'ai eu l'erreur 'Error in parse (texte = math): les vecteurs de longueur négative ne sont pas autorisés' - pas tout à fait sûr pourquoi. Merci! –