#[Java] Say Exercise

1 messages · Page 1 of 1 (latest)

hollow current
#

The task is to spell out a number from 0 to 999,999,999,999 in English. Despite my code being verbose, I've managed to pass 14 out of 19 tests. However, the conversions for 1_234, 1_002_345, and 987_654_621_123L have failed. The instructions suggest, Implement breaking a number up into chunks of thousands, but I might be misunderstanding the process of chunk creation. Could you offer some guidance on the approach I should take to create these chunks?

#

Code:

public class Say {

    private final Map<Integer, String> number0To19 = new HashMap<>();
    private final String[] tensNames = {"", "ten", "twenty", "thirty", "forty", "fifty", "sixty", "seventy", "eighty", "ninety"};
    private final String[] scaleNames = {"", "thousand", "million", "billion"};

    public Say() {
        number0To19.put(0, "zero");
        number0To19.put(1, "one");
        number0To19.put(2, "two");
        number0To19.put(3, "three");
        // From here on, store numbers and strings as pairs up to '19'
    }

    public String say(long number) {
        if (number < 0 || number > 999_999_999_999L) {
            return "Number out of range";
        }

        if (number < 20) {
            return number0To19.get((int) number);
        }

        if (number < 100) {
            int ten = (int) (number / 10);
            int one = (int) (number % 10);
            return tensNames[ten] + (one != 0 ? "-" + number0To19.get(one) : ""); 
        }

        if (number < 1000) {
            int hundred = (int) (number / 100);
            number %= 100;
            int ten = (int) (number / 10);
            int one = (int) (number % 10);
            return number0To19.get(hundred) + " hundred" + (ten != 0 ? " " + tensNames[ten]: "") + (one != 0 ? "-" + number0To19.get(one): "");
        }

        StringBuilder result = new StringBuilder();
        for (int i = scaleNames.length - 1; i >= 0; i--) {
            long divisor = (long) Math.pow(1000, i);
            if (number >= divisor) {
                int chunk = (int) (number / divisor);
                result.append(number0To19.get(chunk)).append(" ").append(scaleNames[i]);
                number %= divisor;
            } 
        }
        return result.toString();

    }
}
#

Error Message:

TEST FAILURE
Message: 
expected: "one thousand two hundred thirty-four"
 but was: "one thousandnull "
Exception: org.opentest4j.AssertionFailedError: 
expected: "one thousand two hundred thirty-four"
 but was: "one thousandnull "
    at java.base/jdk.internal.reflect.DirectConstructorHandleAccessor.newInstance(DirectConstructorHandleAccessor.java:62)
    at java.base/java.lang.reflect.Constructor.newInstanceWithCaller(Constructor.java:502)
    at SayTest.oneThousandTwoHundredThirtyFour(SayTest.java:84)
    at java.base/java.lang.reflect.Method.invoke(Method.java:580)
    at java.base/java.util.ArrayList.forEach(ArrayList.java:1596)
    at java.base/java.util.ArrayList.forEach(ArrayList.java:1596)
#

Error Message:

TEST FAILURE
Message: 
expected: "one million two thousand three hundred forty-five"
 but was: "one milliontwo thousandnull "
Exception: org.opentest4j.AssertionFailedError: 
expected: "one million two thousand three hundred forty-five"
 but was: "one milliontwo thousandnull "
    at java.base/jdk.internal.reflect.DirectConstructorHandleAccessor.newInstance(DirectConstructorHandleAccessor.java:62)
    at java.base/java.lang.reflect.Constructor.newInstanceWithCaller(Constructor.java:502)
    at SayTest.oneMillionTwoThousandThreeHundredFortyFive(SayTest.java:96)
    at java.base/java.lang.reflect.Method.invoke(Method.java:580)
    at java.base/java.util.ArrayList.forEach(ArrayList.java:1596)
    at java.base/java.util.ArrayList.forEach(ArrayList.java:1596)
#

Error Message:

TEST FAILURE
Message: 
expected: "nine hundred eighty-seven billion six hundred fifty-four million three hundred twenty-one thousand one hundred twenty-three"
 but was: "null billionnull millionnull thousandnull "
Exception: org.opentest4j.AssertionFailedError: 
expected: "nine hundred eighty-seven billion six hundred fifty-four million three hundred twenty-one thousand one hundred twenty-three"
 but was: "null billionnull millionnull thousandnull "
    at java.base/jdk.internal.reflect.DirectConstructorHandleAccessor.newInstance(DirectConstructorHandleAccessor.java:62)
    at java.base/java.lang.reflect.Constructor.newInstanceWithCaller(Constructor.java:502)
    at SayTest.nineHundredEightySevenBillionSixHundredFiftyFourThreeHundredTwentyOneThousandOneHundredTwentyThree(SayTest.java:109)
    at java.base/java.lang.reflect.Method.invoke(Method.java:580)
    at java.base/java.util.ArrayList.forEach(ArrayList.java:1596)
    at java.base/java.util.ArrayList.forEach(ArrayList.java:1596)
onyx mist
#

What does your code do with input 1234?

#

Walk us through which lines are adding to the output

hollow current
#
for (int i = scaleNames.length - 1; i >= 0; i--) {
            long divisor = (long) Math.pow(1000, i);
            if (number >= divisor) {
                int chunk = (int) (number / divisor);
                result.append(number0To19.get(chunk)).append(" ").append(scaleNames[i]);

This part is related to the processing of 1234. Currently, it handles the thousands place, but the code fails to process the remaining 234.

expected: "one thousand two hundred thirty-four"
 but was: "one thousandnull "
onyx mist
#

What values of i meet the condition? What does the if body do with those values of i?

#

Do you not understand why your code fails or are you asking for help on how to solve this?

hollow current
#

I think I understand why my code fails. For 1234, it handles the thousands place but does not process the remaining 234. I'm seeking a hint on how to split the string into chunks.

onyx mist
#

You already have code that can handle 234, right?

#

I wouldn't focus too much on that hint. It might be a bit misleading. I think it just means to have that scale list

hollow current
onyx mist
hollow current
#

Would it be better to separate the methods?

onyx mist
#

That shouldn't be necessary but wouldn't hurt.

#

||You can call say() with the chunk without modifying much||

hollow current
#

There isn't a specific reason, but since only the 'say()' method was provided as guidance in the original code, I attempted to implement within that constraint.

#

However, following my approach, it seems like separating the thousands and those below might be better after all.

onyx mist
#

The stubs never provides helper functions. That's not meant to discourage you from defining them.

hollow current
#

I'd like to remove my constraints and proceed towards solving the exercise.

onyx mist
#

Can you call say() with your chunk to handle converting that chunk to a string?

hollow current
#

I can't write the code right now, but I can imagine calling the say() method to return a value.

onyx mist
#

Would that give useful results which can be used in place of those null strings?

hollow current
#

For numbers below 1000, the tests are passing, so I think it should work well.

onyx mist
#

I'd suggest giving that a try

hollow current
#

Thank you. I'll give it a try.

#

I was truly grateful to receive assistance from you, even though I felt a bit nervous.