Question: "Challenge: Configureable Status Format"

Hello,

For this challenge are we supposed to use info we learned in the chapter, i.e. String templates or expressions, or do we need to use a “format string” like mentioned in the challenge? I’m not exactly sure where to start for this challenge; Is there anyone that can point me in the right direction?

Thanks,
Max

2 Likes

Hey blkxltng,

In that exercise, you are intended to implement your own “format string” of the form “(HP)(A) -> H”.
That is, you provide a string like the one above and the player’s stats are used to print something along the lines of “(HP: 100)(Aura: Green) -> Madrigal is in excellent condition!”.

We don’t intend to enforce much about your implementation, but it will almost certainly give you an opportunity to put string templates/interpolation to work.

1 Like

I am a bit confused here. I assume that it should be possible to solve the exercise fully with the knowledge attained form the first three chapters. But in that case I am not sure how to tackle the problem since it seems to require some more advanced stuff. But I am not sure if I am over complicating what is expected of the answer here.

1 Like

rohdester,

That may not be a fair assumption for the challenges in the book. Sometimes, those challenges require a bit of extra digging into the Kotlin standard library or might benefit from some additional domain knowledge from other languages.

They’re not always doable in your first pass, and that’s okay. They don’t have bearing on later content, so feel free to come back to certain challenges when you feel better-equipped.

Thx dgreenhalgh,

OK I see. That makes sense. By doing some digging I am sure I can solve it. I was just not sure whether that was “allowed” or if it should be doable within the first three chapters.

I will return with my solution :slight_smile:

1 Like

So this is my first stab at this. Please let me know if there is a more Kotlin-y way to do this.

// Player status
val statusFormatString = "(HP)(A) -> H"
val formatValueHP = "HP: $healthPoints"
val formatValueA = "Aura: $auraColor"
val formatValueH = "$name $healthStatus"
val formatValueB = if (isBlessed) "YES" else "NO"

var resultString = ""
var didReadAhead = false
for (index in statusFormatString.indices) {
    if (didReadAhead) {
        didReadAhead = false
        continue
    }

    val letter = statusFormatString[index]
    if (letter == 'A') {
        resultString += formatValueA
    } else if (letter == 'B') {
        resultString += formatValueB
    } else if (letter == 'H') {
        val nextIndex = index + 1
        if (nextIndex < statusFormatString.length && statusFormatString[nextIndex] == 'P') {
            resultString += formatValueHP
            didReadAhead = true
        } else {
            resultString += formatValueH
        }
    } else {
        resultString += letter
    }
}

println(resultString)

I did the following making use a few CharSequence.replace() on statusFormatString.

Though there are only “H”, “HP” and “A” (ie. 3) to be replaced. I used 4 replaces. An extra one to replace “HP” to sth else avoiding the ‘H’ in “HP : nnn ” be replaced by “H” when replacing it with healthStatus.

Not pretty but will get the job done.

// Player Status

var hp = “HP: $healthPoints”
var aura = “Aura: $auraColor”
var health = “$name $healthStatus”

println (statusFormatString.replace(“HP”, “P”,false).replace(“H”,health,false).replace(“P”,hp,false).replace(“A”,aura,false))

I was puzzled about this challenge question too, and I’ve been writing code for a very long time. If I take take this instruction literally, then the challenge seems like a hard one to approach.

 For example, a status format string of: val statusFormatString = "(HP)(A) -> H"

Using a string like this to do string formatting requires string replacement, which is not optimal. This is not something you would typically do. So, I would modify statusFormatString.

This one definitely requires reading ahead and revisiting to attempt to solve in the most kotlinesque way - so, if you were stumped, that’s ok - this one is a particularly challenging challenge!

So, here’s one (kotlin style) approach that should work to solve:

mapOf("HP" to "HP: 100%",
 "A" to "red", 
"H\\b" to "HP: excellent!", 
"B" to "YES")
.toList()
.fold("(HP)(A) -> (B): (H)") { acc, (symbol, value) -> 
    acc.replace(symbol.toRegex()) { value } 
}

Notice the ‘toRegex’ step - why? Because of the fact that both H and HP (the format characters) have ‘H’ in common - and simply replacing using the string would cause duplicate replacements! tricccckkkky :smiley:

3 Likes

The upper part of my code is pretty similar to what others posted. I cheated a little bit on the format string and used a semaphore character to indicate an attribute rather than an explicit character in the string to show. Otherwise, it became a computer science class project. I ended up calling the following a provisional win:

// Player status
var statusOutputString = statusFormatString
statusOutputString = statusOutputString.replace(oldValue = "/A",newValue = "Aura: $auraColor", ignoreCase = false)
statusOutputString = statusOutputString.replace(oldValue = "/B",newValue = "Blessed: $isBlessed", ignoreCase = false)
statusOutputString = statusOutputString.replace(oldValue = "/HP",newValue = "Hit Points: $healthPoints", ignoreCase = false)
statusOutputString = statusOutputString.replace(oldValue = "/H",newValue = " $name $healthStatus", ignoreCase = false)
println()
println(statusFormatString)  // for comparison
println(statusOutputString)

This question also confused me. I wasn’t sure what exactly I was being asked to do.
Here is my solution if I interpreted the challenge correctly:

val statusFormatString = "(HP)(A) -> H"
val statusString = statusFormatString
    .replace("HP", "HP: $healthpoints")
    .replace("A", "Aura: $aura")
    .replace("-> H", "-> $description")

Thanks! The .toRegex-hint helped me a lot. :slight_smile:
Is it possible to put variables like auraColor to the map? In the challenge before the color was enhanced.
This is my solution for now:

// Formatting Status String
val hpRegex ="""\bHP\b""".toRegex()
var formattedStatusString = hpRegex.replace(statusFormatString, "HP: $healthPoints")
val hRegex = """\bH\b""".toRegex()
formattedStatusString = hRegex.replace(formattedStatusString, "$name $healthStatus")
val bRegex = """\bB\b""".toRegex()
formattedStatusString = bRegex.replace(formattedStatusString, "Blessed: ${if (isBlessed) "YES" else "NO"}")
val aRegex = """\bA\b""".toRegex()
formattedStatusString = aRegex.replace(formattedStatusString, "Aura: $auraColor")
val fRegex = """\bF\b""".toRegex()
formattedStatusString = fRegex.replace(formattedStatusString, "Faction: $faction")
println(formattedStatusString)
1 Like

Here is my solution.


    val statusFormatString = "(HP)(A) -> H"
    val result: StringBuilder = StringBuilder("")

    for (i in statusFormatString.indices) {

        val replacement = when (statusFormatString[i]) {
            'B' -> "Blessed: ${if (isBlessed) "YES" else "NO"}"
            'A' -> "Aura: $auraColor"
            'H' -> if (((i + 1) < statusFormatString.length) && (statusFormatString[i + 1] == 'P')) {
                "HP: $healthPoints"
            } else {
                "$name $healthStatus"
            }
            'P' -> ""
            else -> {
                statusFormatString[i].toString()
            }
        }

        result.append(replacement)
    }

    print(result)

val statusFormatString = “(HP)(A)(B) → H”
statusFormatString.replace(Regex(“A|B|HP|H”)){
when(it.value){
“B” → “Blessed: ${if (isBlessed) “YES” else “NO”}”
“A” → “Aura: $auraColor”
“HP”-> “HP: $healthPoints”
“H” → “$name $healthStatus”
else → it.value
}
}
.also(::println)