# Re: Factor

Factor: the language, the theory, and the practice.

## Reverse Vowels

Monday, February 12, 2024

Our task today is to “reverse vowels of a string”. This sounds like (and probably is) a coding interview question as well as a LeetCode problem, a Codewars kata, and the second task in the Perl Weekly Challenge #254.

If you don’t want spoilers, maybe stop reading here!

We are going to use Factor to solve this problem as well as a variant that is a bit more challenging.

### Let’s Reverse The Vowels

One of the benefits of the monorepo approach that we have taken to building the extensive Factor standard library is developing higher-level words that solve specific kind of tasks.

One of those is arg-where – currently in the miscellaneous sequences.extras vocabulary – which we can use to find all the indices in a string that contain a vowel?:

``````IN: scratchpad "hello" [ vowel? ] arg-where .
V{ 1 4 }
``````

We’ll want to group the beginning and ending indices, ignoring the middle index if the number of indices is odd since it would not change:

``````: split-indices ( indices -- head tail )
dup length 2/ [ head-slice ] [ tail-slice* ] 2bi ;
``````

We can then build a word to reverse specified indices:

``````: reverse-indices ( str indices -- str )
split-indices <reversed> [ pick exchange ] 2each ;
``````

And then use it to reverse the vowels:

``````: reverse-vowels ( str -- str )
dup >lower [ vowel? ] arg-where reverse-indices ;
``````

And see how it works:

``````IN: scratchpad "factor" reverse-vowels .
"foctar"

"cencitanetavo"
``````

Pretty cool!

### Let’s Reverse The Vowels, Maintain The Case

A somewhat more challenging task is to reverse the vowels, and to swap their letter case.

Let’s start by building a word to swap the case of two letters:

``````: swap-case ( a b -- a' b' )
2dup [ letter? ] bi@ 2array {
{ { t f } [ [ ch>upper ] [ ch>lower ] bi* ] }
{ { f t } [ [ ch>lower ] [ ch>upper ] bi* ] }
[ drop ]
} case ;
``````

And then another word to exchange two indices, but also swap their case:

``````: exchange-case ( i j seq -- )
[ '[ _ nth ] bi@ swap-case ]
[ '[ _ set-nth ] bi@ ] 3bi ; inline
``````

A word to reverse the indices, but also swap their case:

``````: reverse-indices-case ( str indices -- str )
split-indices <reversed> [ pick exchange-case ] 2each ;
``````

And, finally, a word to reverse the vowels, but also swap their case:

``````: reverse-vowels-case ( str -- str )
dup >lower [ vowel? ] arg-where reverse-indices-case ;
``````

And then see how it works:

``````IN: scratchpad "FActor" reverse-vowels-case .
"FOctar"
``````

A pretty fun problem!