{{ message }}

Instantly share code, notes, and snippets.

# ajc2/covfefeify_explanation.md

Last active Apr 12, 2018
A description of a PPCG answer.

# Explanation time!

I'm also in the mood to write a long, detailed explanation. SmileBASIC is fairly obscure, so hopefully someone learns from it. This is an explanation to this answer on PPCG.

# The vowel list

``````V\$="AEIOUY
``````

I store the list of which letters are vowels in a string named `V\$`; there is no "is this a vowel" builtin, and I refer to this list three times, so it's best to store it.

# Taking input

``````LINPUT W\$
``````

The `LINPUT` keyword reads a line of text from the console and stores it to a string variable (here, `W\$`; string variables have names that end with `\$`.) I use this to take in the word we're covfefe-ifying.

# The `INSTR` function

I use this a few times coming up, so I should probably explain what it does. `INSTR()` takes the form:

``````index% = INSTR(string\$, substring\$)
``````

This returns the location of `substring\$` within `string\$`, zero-indexed, or -1 if `string\$` does not contain `substring\$`. This is useful for a great many things, but in this program I simply use it to check if or where a given letter is in a list of letters.

# Finding the first sound group

The task of figuring out where the first sound group ends really breaks down to this: find the first consonant which is preceded by a vowel. Of course, there is no builtin or simple way of doing this, so you have to make our own way!

To see if a letter is a consonant, you really only need to know which ones are vowels. So, the vowel list `V\$` does double-duty here. I use `INSTR` to check either case. If a letter is a vowel, it will be a substring of `V\$`, and if it isn't, it won't. The conditional then, effectively breaks down to this:

``````INSTR(V\$, W\$[I-1]) >= 0 && INSTR(V\$, W\$[I]) < 0
``````

where `W\$[I]` is the `I`th character in our word, or the first consonant which follows a vowel.

Of course, I have to loop over the string for `I`. I chose to do this with a `REPEAT` loop and incrementing `I` myself, because it's actually the shortest.

``````REPEAT I=I+1 UNTIL INSTR(V\$, W\$[I-1]) >= 0 && INSTR(V\$, W\$[I]) < 0
``````

Now, `I` will store the right index for building the result. This also guarantees that `I` starts at 1 for the check; otherwise, our code would break. Of course, this can be golfed significantly.

``````REPEAT I=I+1UNTIL.<INSTR(V\$,W\$[I-1])&&.>INSTR(V\$,W\$[I])
``````

Replace `0` with `.` and flip the comparisons around, compressing as much whitespace as possible in the process.

# Finding the next vowel

Now we have to find the first vowel following the first sound group. This is very straighforward; just use pretty much the same process as before.

``````J=I
WHILE.>INSTR(V\$,W\$[J])J=J+1WEND
``````

We copy `I` to `J` because we need both values for later and this check has to start at `I`.

# Covfefe-ing the word

Now, given what we know about the input word, it has to be covfefe-ified. This is done in two steps.

## The first sound group

``````LEFT\$(W\$,I+1)
``````

Since `I` remembers where our split point is, we just use `LEFT\$()` to extract the first `I+1` characters in the word, which is the first sound group. Handy!

## The second sound group

This process is a bit more complex. First off, we have to take the consonant at `I` and figure out its alternative. There's a table given in the question text that describes the mapping, and here it's stored in two strings.

``````"PGTVKHJGLMNBQRZDFWXS"[INSTR("BCDFGHJKLMNPQRSTVWXZ",W\$[I])]
``````

In case you haven't gathered yet, we can use the `[]` indexing operator on strings, like you would in an array, to get (a copy of) the character contained at the given index. The first long string is the set of alternatives for the list of consonants in the other string. To find a consonant's alternative, find its index in the list of consonants and get the character at the index in the list of alternatives. Simple!

Then, we have to take the vowel at `J` and put it after this consonant. This string is then doubled; in other words, `AJ` becomes `AJAJ` where `A` is the consonant alternative from above and `J` is the vowel at `J`.

``````("PGTVKHJGLMNBQRZDFWXS"[INSTR("BCDFGHJKLMNPQRSTVWXZ",W\$[I])]+W\$[J])*2
``````

Multiplying a string by an int in SB repeats the string that number of times (1 is then the identity, and 0 is an empty string; negative numbers are obviously illegal.) Multiply by 2 and we get the doubling we desire.

## Output

Concatenate the two sound groups above and give them to a `PRINT` (written here using its `?`) alias, and we have output!

``````?LEFT\$(W\$,I+1)+("PGTVKHJGLMNBQRZDFWXS"[INSTR("BCDFGHJKLMNPQRSTVWXZ",W\$[I])]+W\$[J])*2
``````

Challenge complete, and in 195 bytes!

# The full program

``````V\$="AEIOUY
LINPUT W\$REPEAT I=I+1UNTIL.<=INSTR(V\$,W\$[I-1])&&.>INSTR(V\$,W\$[I])J=I
WHILE.>INSTR(V\$,W\$[J])J=J+1WEND?LEFT\$(W\$,I+1)+("PGTVKHJGLMNBQRZDFWXS"[INSTR("BCDFGHJKLMNPQRSTVWXZ",W\$[I])]+W\$[J])*2
``````