如何用R语言从生成的全排列组合中筛选出逻辑谜题的正确解
Nice work getting all the permutations and nickname pairings generated—that’s the hard part out of the way! Let’s break down how to filter these combinations to find the valid solution that matches your puzzle’s logical rules.
Step 1: Fix the Nickname Mappings (Get Valid One-to-One Matches)
Your current result.list includes every possible single name-nickname pair, but we need one-to-one mappings (each real name gets exactly one unique nickname, and vice versa). To generate these valid mappings, we can use permn() on the nickname list—each permutation of nicknames corresponds to a unique, valid pairing with your real names:
library(combinat) # Ensure this package is loaded (you used it for permn() already) real_names <- c("Bill", "Ernie", "Oscar", "Sammy", "Tony") nicknames <- c("Slats", "Stretch", "Tiny", "Tower", "Tree") # Generate all valid one-to-one nickname mappings nickname_mappings <- lapply(permn(nicknames), function(perm) { setNames(perm, real_names) # Names = real names, values = nicknames }) # Example of a valid mapping: nickname_mappings[[1]] # Bill Ernie Oscar Sammy Tony # "Slats" "Stretch" "Tiny" "Tower" "Tree"
Step 2: Write a Rule-Checking Function
Next, translate your puzzle’s logical rules into an R function that checks if a given height order and nickname mapping are valid. For example, if your puzzle had rules like:
- Stretch is the second-tallest player
- Bill’s nickname isn’t Tiny
- Tony is shorter than Oscar
- Tower is the shortest player
Your function would look like this (replace these rules with your actual puzzle rules):
# Define your puzzle's rules here is_valid_solution <- function(height_order, nickname_map) { # Assume height_order[1] = tallest, height_order[5] = shortest (adjust if needed) # Rule 1: Stretch is second-tallest rule1 <- nickname_map[height_order[2]] == "Stretch" # Rule 2: Bill's nickname isn't Tiny rule2 <- nickname_map["Bill"] != "Tiny" # Rule 3: Tony is shorter than Oscar (higher index = shorter) rule3 <- which(height_order == "Tony") > which(height_order == "Oscar") # Rule 4: Tower is the shortest rule4 <- nickname_map[height_order[5]] == "Tower" # All rules must be satisfied all(rule1, rule2, rule3, rule4) }
Step 3: Iterate Through All Combinations to Find Valid Solutions
Now loop through every possible height permutation and nickname mapping, using your rule function to filter valid solutions:
# Convert your matrix_version into a list of height order vectors height_perms <- lapply(1:ncol(matrix_version), function(col) matrix_version[, col]) # Search for all valid solutions valid_solutions <- list() for (perm in height_perms) { for (mapping in nickname_mappings) { if (is_valid_solution(perm, mapping)) { valid_solutions[[length(valid_solutions) + 1]] <- list( height_order = perm, nickname_mapping = mapping ) } } } # Print results if (length(valid_solutions) > 0) { cat("Found", length(valid_solutions), "valid solution(s):\n") for (i in seq_along(valid_solutions)) { cat("\nSolution", i, ":\n") cat("Height order (tallest to shortest):", paste(valid_solutions[[i]]$height_order, collapse = " > "), "\n") cat("Nickname mappings:\n") print(valid_solutions[[i]]$nickname_mapping) } } else { cat("No valid solutions found—double-check your logical rules for accuracy!") }
Key Notes
- Height Order Direction: Make sure the index logic in your rule function matches whether
height_order[1]is the tallest or shortest player (adjust if your permutations are ordered from shortest to tallest). - Rule Accuracy: Even a single miswritten rule will prevent finding the solution, so double-check each condition against your puzzle’s wording.
- Efficiency: With 5 players, we’re only checking 120 (height permutations) × 120 (nickname mappings) = 14,400 combinations—this is tiny for R, so brute force works perfectly here.
内容的提问来源于stack exchange,提问作者stats_noob

