Skip to content

Instantly share code, notes, and snippets.

@theotherzach
Created March 17, 2014 14:18
Show Gist options
  • Save theotherzach/9600002 to your computer and use it in GitHub Desktop.
Save theotherzach/9600002 to your computer and use it in GitHub Desktop.

Placeholder For Bottles Solutions

@sw17ch
Copy link

sw17ch commented Mar 17, 2014

Here's a Haskell version for fun:

#!/usr/bin/env runghc

countWith :: [Integer]
countWith = reverse [0..99]

main :: IO ()
main = putStr $ concatMap output countWith

output :: Integer -> String
output n = concat [lookAtBottles n, "\n", passBottles (n - 1), "\n\n"]

noun :: Integer -> String
noun 1 = "bottle"
noun _ = "bottles"

lookAtBottles :: Integer -> String
lookAtBottles 0 = "No more bottles of beer on the wall, no more bottles of beer."
lookAtBottles n = concat [s, " ", b, " of beer on the wall, ", s, " ", b, " of beer."]
  where
    s = show n
    b = noun n

passBottles :: Integer -> String
passBottles n | n == (-1) = "Go to the store and buy some more, 99 bottles of beer on the wall."
              | n == 0 = "Take it down and pass it around, no more bottles of beer on the wall."
              | n > 0 = "Take one down and pass it around, " ++ s ++ " " ++ (noun n) ++ " of beer on the wall."
              | otherwise = error $ "Invalid bottle count: " ++ s
  where
    s = show n

@theotherzach
Copy link
Author

Nice. I'm glad @sw17ch went with Haskell because I'm curious to see how the type system plays with some of the variations.

Are these all the conditionals, or did I miss any? (I'm not counting the exception because I don't think that code path is ever actually hit in the tests..)

  • lookAtBottles: n == 0
  • lookAtBottles: n != 0
  • noun: n != 1
  • noun: n == 1
  • passBottles: n - 1 == -1
  • passBottles: n - 1 == 0
  • passBottles: n - 1 > 0

@DarthStrom
Copy link

Here's mine in Groovy. Bryan and I have talked about this before and I like his approach of handling the 3 special cases completely separately to reduce some of the complexity.

class Bottles {
    def verse(n) {
        switch (n) {
            case 0:
                return """\
No more bottles of beer on the wall, no more bottles of beer.
Go to the store and buy some more, 99 bottles of beer on the wall.
"""
            case 1:
                return """\
1 bottle of beer on the wall, 1 bottle of beer.
Take it down and pass it around, no more bottles of beer on the wall.
"""
            case 2:
                return """\
2 bottles of beer on the wall, 2 bottles of beer.
Take one down and pass it around, 1 bottle of beer on the wall.
"""
            default:
                return """\
${n} bottles of beer on the wall, ${n} bottles of beer.
Take one down and pass it around, ${n-1} bottles of beer on the wall.
"""
        }
    }

    def verses(first, last) {
        def song = ""
        (first..last).each { song += verse(it) + "\n" }
        song
    }

    def sing() {
        verses(99, 0)
    }
}

@bryanschoeff
Copy link

Yeah Zach, we have talked about this one sooooo much in the past, I feel like I know where this might be going....

class Bottles

  def sing
    verses 99, 0
  end

  def verses start, finish
    result = ""
    start.downto finish do |i|
      result += "#{verse i}\n"
    end
    result
  end

  def verse number
    case number
    when 0
      "No more bottles of beer on the wall, no more bottles of beer.\n" \
      "Go to the store and buy some more, 99 bottles of beer on the wall.\n"
    when 1
      "1 bottle of beer on the wall, 1 bottle of beer.\n" \
      "Take it down and pass it around, no more bottles of beer on the wall.\n"
    when 2
      "2 bottles of beer on the wall, 2 bottles of beer.\n" \
      "Take one down and pass it around, 1 bottle of beer on the wall.\n"
    when 3..99
      "#{number} bottles of beer on the wall, #{number} bottles of beer.\n" \
      "Take one down and pass it around, #{number - 1} bottles of beer on the wall.\n"
    end
  end
end

@bryanschoeff
Copy link

...and F#...cause...I'm an asshole

type Bottles() =

  member x.verse(number) = 
    match number with
      | 0 -> "No more bottles of beer on the wall, no more bottles of beer.\n\
              Go to the store and buy some more, 99 bottles of beer on the wall.\n"
      | 1 -> "1 bottle of beer on the wall, 1 bottle of beer.\n\
              Take it down and pass it around, no more bottles of beer on the wall.\n"
      | 2 -> "2 bottles of beer on the wall, 2 bottles of beer.\n\
              Take one down and pass it around, 1 bottle of beer on the wall.\n"
      | _ -> sprintf "%d bottles of beer on the wall, %d bottles of beer.\n\
                      Take one down and pass it around, %d bottles of beer on the wall.\n" number number (number - 1)

  member x.verses(start, finish) =
    if start = finish then sprintf "%s\n" (x.verse finish)
    else sprintf "%s\n%s" (x.verse start) (x.verses((start - 1), finish))

  member x.sing() =
    x.verses(99, 0)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment