library(tidyverse)
library(readxl)
path = "Excel/800-899/805/805 Vowels in Increasing or Decreasing Order.xlsx"
input = read_excel(path, range = "A2:B16")
test = read_excel(path, range = "D2:G5")
vowel_factor = factor(c("a", "e", "i", "o", "u"),
levels = c("a", "e", "i", "o", "u"),
ordered = TRUE)
result = input %>%
mutate(
vowels = str_extract_all(str_to_lower(Rivers), "[aeiou]"),
ord = map_chr(vowels, ~ {
d = diff(match(.x, levels(vowel_factor)))
if (all(d >= 0) & any(d > 0)) "increasing"
else if (all(d <= 0) & any(d < 0)) "decreasing"
else "neither"
})
) %>%
filter(ord != "neither") %>%
select(Group, Rivers) %>%
arrange(Group, Rivers) %>%
mutate(rn = row_number(), .by = Group) %>%
pivot_wider(names_from = rn, names_glue = "River{rn}" , values_from = Rivers)
all.equal(result, test, check.attributes = FALSE)
# [1] TRUEExcel BI - Excel Challenge 805
excel-challenges
excel-formulas
🔰 List the Rivers which contain at least 2 distinct vowels and vowels are either in increasing order (>=) or decreasing order (<=) but not

Challenge Description
🔰 List the Rivers which contain at least 2 distinct vowels and vowels are either in increasing order (>=) or decreasing order (<=) but not
Solutions
- Logic: Read the workbook ranges needed for the challenge; Derive the required intermediate columns; Parse the packed text or string structure; Aggregate or rank the data at the required grouping level.
- Strengths: The solution stays close to the text pattern itself, which makes the extraction logic easy to audit.
- Areas for Improvement: The solution assumes the workbook layout and selected ranges remain stable, so any structural change in the sheet would require small adjustments.
- Gem: A small number of well-targeted text patterns does most of the heavy lifting.
import pandas as pd
import numpy as np
import re
path = "800-899/805/805 Vowels in Increasing or Decreasing Order.xlsx"
input = pd.read_excel(path, usecols="A:B", skiprows=1, nrows=15)
test = pd.read_excel(path, usecols="D:G", skiprows=1, nrows=3).rename(columns=lambda col: col.replace('.1', ''))
vowel_levels = ['a', 'e', 'i', 'o', 'u']
vowel_map = {v: i for i, v in enumerate(vowel_levels)}
input['riv'] = input['Rivers'].str.lower()
input['vowels'] = input['riv'].apply(lambda s: re.findall(r'[aeiou]', s))
input['inc'] = input['vowels'].apply(lambda v: all(np.diff([vowel_map[x] for x in v]) >= 0))
input['dec'] = input['vowels'].apply(lambda v: all(np.diff([vowel_map[x] for x in v]) <= 0))
input['vowel_order'] = np.select(
[input['inc'] & ~input['dec'], ~input['inc'] & input['dec']],
['increase', 'decrease'],
default='neither'
)
filtered = input[input['vowel_order'] != 'neither'].copy()
filtered = filtered[['Group', 'Rivers']].sort_values(['Group', 'Rivers'])
filtered['rn'] = filtered.groupby('Group').cumcount() + 1
result = filtered.pivot(index='Group', columns='rn', values='Rivers')
result.columns = [f"River{col}" for col in result.columns]
result = result.reset_index()
print(result.equals(test)) # TrueThe Python version follows the same grouped logic and keeps the transformation explicit in a dataframe pipeline.
Difficulty Level
Medium
The individual steps are manageable, but the correct transformation pattern is not obvious from the raw data.