DEV Community

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!

Discussion

pic
Editor guide
Collapse
avalander profile image
Avalander

Haskell

mouthSize :: String -> String
mouthSize "alligator" = "small"
mouthSize x           = "wide"
Collapse
aminnairi profile image
Amin

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!

Collapse
lukaszahradnik profile image
Lukáš Zahradník

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)

Collapse
avalander profile image
Avalander

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

Thread Thread
lukaszahradnik profile image
Lukáš Zahradník

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

Collapse
peledzohar profile image
Zohar Peled

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";
}
Collapse
nickholmesde profile image
Nick Holmes

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

Collapse
peledzohar profile image
Zohar Peled

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

Thread Thread
nickholmesde profile image
Nick Holmes

and not handling case insensitivity.

Collapse
nickholmesde profile image
Nick Holmes

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.

Collapse
citizen428 profile image
Michael Kohl

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"
Collapse
nickholmesde profile image
Nick Holmes

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.

Collapse
aminnairi profile image
Amin

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");
    }
}
Collapse
kespri profile image
kespri

Swift :

func mouthSize(animal: String) -> String {
    animal.lowercased() == "aligator" ? "small" : "wide"
}
Collapse
nickholmesde profile image
Nick Holmes

Good example of why unit tests are important!

Collapse
kespri profile image
kespri

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

Thread Thread
nickholmesde profile image
Nick Holmes

Sorry. You nailed it, but misspelled alligator.

Collapse
erezwanderman profile image
erezwanderman

JS

mouth_size = animal => /^alligator$/i.test(animal) ? 'small' : 'wide'
Collapse
vaibhavyadav1998 profile image
Vaibhav Yadav

In Go.

import "strings"

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

    return "wide"
}
Collapse
benchislett profile image
Benjamin Chislett
const mouth_size = a => (a == "alligator") ? "small" : "wide"
Collapse
hyftar profile image
Simon Landry

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

Collapse
hyftar profile image
Simon Landry

Ruby:

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