loading...

Daily Challenge #135 - The Wide Mouthed Frog!

thepracticaldev profile image dev.to staff ・1 min read

The wide mouth frog is particularly interested in the eating habits of other creatures.

He just can't stop asking the creatures he encounters what they like to eat. But then he meets the alligator who just LOVES to eat wide-mouthed frogs!

When he meets the alligator, it then makes a tiny mouth.

Your goal in this kata is to create complete the mouth_size method this method takes one argument animal which corresponds to the animal encountered by the frog. If this one is an alligator (case insensitive) return small otherwise return wide.


This challenge comes from nbeck on CodeWars. Thank you to CodeWars, who has licensed redistribution of this challenge under the 2-Clause BSD License!

Want to propose a challenge idea for a future post? Email yo+challenge@dev.to with your suggestions!

Posted on by:

thepracticaldev profile

dev.to staff

@thepracticaldev

The hardworking team behind dev.to ❤️

Discussion

pic
Editor guide
 

Haskell

mouthSize :: String -> String
mouthSize "alligator" = "small"
mouthSize x           = "wide"
 

I see you are learning about Haskell. Congratulations! This isn't an easy language to handle (I'm am myself a learner, but aren't we all?).

I guess in your solution, cases like "ALLIGATOR" and "aLlIgAtOr" won't match the first pattern and will return "wide". But the OP was mentioning that the "alligator" animal was case insensitive.

So I'm proposing this solution.

import Data.Char (toLower, isSpace)
import Data.List (dropWhile, dropWhileEnd)

trim :: String -> String
trim = dropWhile isSpace . dropWhileEnd isSpace

mouthSize :: String -> String
mouthSize animal 
    | (trim $ map toLower animal) == "alligator" = "small"
    | otherwise = "wide"

main :: IO ()
main = do
    print $ mouthSize "alligator"       -- small
    print $ mouthSize "   alligator   " -- small
    print $ mouthSize "aLlIgAtOr"       -- small
    print $ mouthSize "fox"             -- wide

I took the opportunity to handle the cases where there was too much spaces (as I did in my TypeScript proposal).

This may not be the final solution, or prone to enhancement, but I guess it is a good one. We can make it better together as a community!

 

I don't know much about Haskell, but isn't it more "proper" to write

mouthSize _           = "wide"

rather than

mouthSize x           = "wide"

(Results are the same)

 

Maybe, I don't write a lot of Haskell so I couldn't say.

It's used to match any pattern and ignore the value. Right now the value is bounded to x which isn't used.

 

Am I missing something here or is this really not a challenge at all?

public string mouth_size(string animal)
{
    return string.Equals(animal, "alligator", StringComparison.OrdinalIgnoreCase) ?
         "small" :
         "wide";
}
 

Challenge or not, at this time there are 6 solutions posted here, and (I believe) only 2 are completely to spec.

 

Most seem legit to me... Maybe a typo here and there...

and not handling case insensitivity.

 

F#:

let mouth_size = function
    | IgnoreCase "alligator" -> "small"
    | _ -> "wide"

But that uses an active pattern to make it case insensitive, like this;

let (|IgnoreCase|_|) a b = 
    match String.Equals(a, b, StringComparison.OrdinalIgnoreCase) with
    | true -> Some()
    | false -> None

Active Patterns provide a real nice way to move the ugly details of the case insensitive comparison out the the way.

 

Did you ever see Don Syme's talk "F# code I love"? It really got me to reconsider how I write F#, i.e. no match that's just an if or active patterns that just add a layer of indirection.

let mouthSize x =
    if String.Equals(x, "alligator", StringComparison.OrdinalIgnoreCase) 
    then "small"
    else "wide"
 

Well, I guess in this case it's down to personal preference and style.

I think that the length of String.Equals call detracts from comprehending what the code is doing, so moving it elsewhere is achieves more than just adding a layer of indirection.

I'm also not against using match over a simple bool- I quite like the kind of tabular layout of the code.

 

TypeScript

"use strict";

class MouthSizeArgumentCountError extends Error {
    constructor(message: string) {
        super(message);

        this.name = "MouthSizeArgumentCountError";
    }
}

class MouthSizeTypeError extends Error {
    constructor(message: string) {
        super(message);

        this.name = "MouthSizeArgumentCountError";
    }
}

type MouthSize = "small" | "wide";

function mouthSize(animal: string): MouthSize {
    if (arguments.length !== 1) {
        throw new MouthSizeArgumentCountError("Expected exactly one argument");
    }

    if (typeof animal !== "string") {
        throw new MouthSizeTypeError("Expect argument to be a string");
    }

    if (animal.trim().toLowerCase() === "alligator") {
        return "small";
    }

    return "wide";
}

console.log(mouthSize("alligator")); // "small"
console.log(mouthSize("aLlIgAtOr")); // "small"
console.log(mouthSize("fox"));      // "wide"

try {
    // @ts-ignore
    mouthSize();
    // @ts-ignore
    mouthSize("fox", "alligator");
} catch (error) {
    if (error instanceof MouthSizeArgumentCountError) {
        console.log("argument count error");
    }
}

try {
    // @ts-ignore
    mouthSize(123);
} catch (error) {
    if (error instanceof MouthSizeTypeError) {
        console.log("argument type error");
    }
}
 

Swift :

func mouthSize(animal: String) -> String {
    animal.lowercased() == "aligator" ? "small" : "wide"
}
 

Good example of why unit tests are important!

 

Thanks a lot for this useful input, that's a good example of why constructive criticism is important.

Sorry. You nailed it, but misspelled alligator.

 

JS

mouth_size = animal => /^alligator$/i.test(animal) ? 'small' : 'wide'
 

In Go.

import "strings"

func mouthSize(animal string) string {
    if strings.ToLower(animal) == "alligator" {
        return "small"
    }

    return "wide"
}
 
const mouth_size = a => (a == "alligator") ? "small" : "wide"
 

The animal isn't case insensitive in your code mounth_size('aLlIgAtOr') will return 'wide' while it should return 'small'

 

Ruby:

def mouth_size(animal)
  animal =~ /alligator/i ? 'small' : 'wide'
end