When is the Letter entered into the map? Also, 'if (LetterSeen[Letter])' is also asking if the Letter has the value of true!

It was unclear to me exactly what our ‘if’ statement was asking and exactly when the Letter was entered into the map. Was it asking if the letter is in the table or was it asking if it was set to true?

Turns out it’s asking if the Letter is set to true. I proved this by changing my map a little bit:

TMap <char, int> LetterSeen;

	for (auto Letter : Guess)
	{
		Letter = tolower(Letter);

		if (LetterSeen[Letter] == 1)
		{
			return false;
		}
		else
		{
			LetterSeen[Letter]++;
		}

As you can see, I changed it from <char, bool> to <char, int>. I enter each new letter with an increment (giving the letter a value of 1 upon entering the table) and my ‘if statement’ asks if the Letter has the value of 1.

Interestingly, if I set my ‘if statement’ to ask if the Letter has the value of 0, it even says valid guesses like ‘slime’ has repeating letters. This tells me that somehow, before the ‘if statement’, the Letter is already entered into the map.

I watched the video and Sam addressed this. It turns out that the it is the ‘if statement’ that enters the character into the map! I think…

Ok, I don’t know if I understood your question, but let’s break it down.
Short Answer

  • Question (I think): When is the Letter entered into the map?

At first, when the map is created, there are no letters on it (you can run your debugger on Visual Studio and put a breakpoint after declaring the TMap, you’ll see it’s empty. In the if statement, the “if” asks to the map “Hey, what’s the value of ‘Letter’ in your dictionary?”

The dictionary won’t find “Letter” on it, so it will answer the default value of a bool: False.

  • Second question: What’s the “If” asking?

It is asking if the letter you’re examining is set on the dictionary “LetterSeen” as true, so it’s basically asking if that letter was already seen. If it was, it means it’s a duplicate letter, if it wasn’t, you will set it as “seen”.

Long Answer

First of all, I got the code developed in the course for the current lesson you are “Range-based for loop”. I got it going on the GitHub page for the project, then going into “Commits” above the file tree and choosing the commit “BC35 Range-based for Loop”, finally going to “View” to see how the whole code looked like at that moment.

Now, in the title, you asked: “What’s our ‘if’ statement was asking and exactly when the Letter was entered into the map?”.

When he creates the TMap

TMap<char, bool> LetterSeen;

Any value that you try, for example

LetterSeen['c']

is set as false, because it still doesn’t exist in the dictionary, so the dictionary will reply with the default value of booleans (“false”), so:

if (LetterSeen[Letter]) {// if the letter is in the map
	return false; // we do NOT have an isogram
} else { 
	LetterSeen[Letter] = true;// add the letter to the map *<--- HERE is where the letter enters the map, when you assign the value to it.*
}

Considering that “Letter” is the current letter on the “for” loop (for example, if you’re using the “for” loop on the word “boom”, “Letter” will be “b”, then “o”, then “o”, then “m”).

When he checks in the dictionary for the letter he’s going through, he will check if the value of that letter in the dictionary is “true” or “false”, if it’s true, he’ll return false for the method “IsIsogram” (“This is not an isogram, because I’ve been through this word and I’ve found this letter before”), if the value is false, it means that he didn’t find this letter before, because “false” is the default value of the letters. THIS is what our “if” is asking.

If this is too much complicated, let’s try simulating this whole function:
The input is going to be: boom (this is gonna be the variable Word)

if (Word.length() <= 1) { return true; }
// Since "boom" has 4 letters, this won't return true

TMap<char, bool> LetterSeen; 
// Every letter we try will start with false, so b -> false, o -> false, m -> false, 
// because the map is empty and this is the default value of booleans,
// once we set them to true, they enter the dictionary

// the letters will be: 1st - b, 2nd - o, 3rd - o, 4th -m
for (auto Letter : Word) 	
{
	// Since every letter is already lowercased, this won't change anything
	Letter = tolower(Letter); 
	
	// On the first time: LetterSeen['b'] is false, so we will go to else
	// On the second time: LetterSeen['o'] is false, so we will go to else
	// On the third time: LetterSeen['o'] is true, because we have already seen "o"
	if (LetterSeen[Letter]) {
		// Since we already saw a letter, this means that there are repeated letters, so this is not an isogram, so return false
		return false;
	} else { 
		// On the first time: LetterSeen['b'] is false, so now we will change it to "true", saying that we already saw 'b'
		// On the second time: LetterSeen['o'] is false, so now we will change it to "true", saying that we already saw 'o'
		LetterSeen[Letter] = true;
	}	
}

return true; // for example in cases where /0 is entered

Your approach is also valid because you will change it to the number of times you have seen that letter. And the default value of an int in a dictionary is 0, so whenever the dictionary doesn’t find the letter you’re asking for, it will return 0. That explains the behaviour of your code, when you set it to 0.

Hope this helps. :smiley:

2 Likes

My biggest issue with the way you’ve done this is the use of LetterSeen[Letter}++

While it’s true that in most normal cases, especially in the context of this program, this will probably work fine, LetterSeen[Letter], until the assignment or (in this case) incrementor statement is uninitialized. You could just as easily wind up with LetterSeen[Letter] == -888232305283098. Or so was demonstrated to us early on with using cout on an uninitialized variable.

Using true and false there is only one possible outcome, the variable is set to true (1) or it is not, making uninitialized values significantly safer.

Hopefully someone will come along and fact check me, as much for my education as anyone else’s.

Damn, this was my post from half a year ago. Feels weird answering my own question, but I’ve come a long way and I can see that I really misunderstood (and underestimated the simplicity of) maps.

Q: When is the letter entered into the map?
A: if ( Map [Letter] ). It’s that simple.
It’s not immediately obvious that THAT statement adds anything to the map, but it does.
It also initializes the value of that ‘Letter’ to ‘false’, which we then change to ‘true’ if it wasn’t already.
Since it initializes it to ‘false’, the if statement itself is also ‘false’, meaning we skip to the ‘else’ statement!

So, I was kind of right. ‘if (LetterSeen[Letter])’ IS asking if the letter has a value of true.
If it’s already in the map, it has the value of true (thanks to the ‘else’ statement).
If it’s not in the map, the map has to add it to the map (along with the value of ‘false’) to even provide an answer.
Easy, huh?

1 Like

This topic was automatically closed 24 hours after the last reply. New replies are no longer allowed.

Privacy & Terms