diff --git a/exercises/beer-song/.meta/exercise-data.yaml b/exercises/beer-song/.meta/exercise-data.yaml new file mode 100644 index 00000000..a9c742d0 --- /dev/null +++ b/exercises/beer-song/.meta/exercise-data.yaml @@ -0,0 +1,54 @@ +exercise: BeerSong +plan: 9 +subs: sing +tests: |- + for my $case ( recurse_cases($C_DATA) ) { + # Your result should be a string, which is transformed into + # an array here when matching for a cleaner test output. + is( + [split("\n", sing({ + bottles => $case->{input}{startBottles}, + verses => $case->{input}{takeDown}, + }))], + $case->{expected}, + $case->{description} + ); + } + + sub recurse_cases { + my $obj = shift; + return $obj->{cases} + ? map recurse_cases($_), @{ $obj->{cases} } + : $obj + } + +example: |- + sub sing { + my ($input) = @_; + my @verses; + for ( 1..$input->{verses} ) { + if ( $input->{bottles} ) { + my $s = $input->{bottles} > 1 ? 's' : ''; + my $one = $input->{bottles} == 1 ? 'it' : 'one'; + chomp(my $str = <{bottles} bottle$s of beer on the wall, $input->{bottles} bottle$s of beer. + Take $one down and pass it around, + VERSE + push @verses, $str . (--$input->{bottles} || 'no more') . ' bottle' . ($input->{bottles} == 1 ? '' : 's') . ' of beer on the wall.'; + } + else { + chomp(my $str = <= $end ) { - $song .= verse($start); - $song .= "\n"; - $start--; - } - - return $song; -} - -sub _line1 { - my $num = shift; - - if ( $num > 1 ) { - return - "$num bottles of beer on the wall, $num bottles of beer.\n"; - } - elsif ( $num == 1 ) { - return "1 bottle of beer on the wall, 1 bottle of beer.\n"; - } - elsif ( $num == 0 ) { - return - "No more bottles of beer on the wall, no more bottles of beer.\n"; - } -} - -sub _line2 { - my $num = shift; - - if ( $num > 2 ) { - $num--; - return - "Take one down and pass it around, $num bottles of beer on the wall.\n"; - } - elsif ( $num == 2 ) { - return - "Take one down and pass it around, 1 bottle of beer on the wall.\n"; - } - elsif ( $num == 1 ) { - return - "Take it down and pass it around, no more bottles of beer on the wall.\n"; - } - elsif ( $num == 0 ) { - return - "Go to the store and buy some more, 99 bottles of beer on the wall.\n"; - } -} -__PACKAGE__; diff --git a/exercises/beer-song/.meta/solutions/BeerSong.pm b/exercises/beer-song/.meta/solutions/BeerSong.pm new file mode 100644 index 00000000..2ec6342d --- /dev/null +++ b/exercises/beer-song/.meta/solutions/BeerSong.pm @@ -0,0 +1,36 @@ +package BeerSong; +use strict; +use warnings; +use Exporter 'import'; +our @EXPORT_OK = qw(sing); + +sub sing { + my ($input) = @_; + my @verses; + for ( 1 .. $input->{verses} ) { + if ( $input->{bottles} ) { + my $s = $input->{bottles} > 1 ? 's' : ''; + my $one = $input->{bottles} == 1 ? 'it' : 'one'; + chomp( my $str = <{bottles} bottle$s of beer on the wall, $input->{bottles} bottle$s of beer. +Take $one down and pass it around, +VERSE + push @verses, + $str + . ( --$input->{bottles} || 'no more' ) + . ' bottle' + . ( $input->{bottles} == 1 ? '' : 's' ) + . ' of beer on the wall.'; + } + else { + chomp( my $str = <); }; +plan 9; + +imported_ok qw(sing) or bail_out; + +for my $case ( recurse_cases($C_DATA) ) { + + # Your result should be a string, which is transformed into + # an array here when matching for a cleaner test output. + is( + [ split( + "\n", + sing( + { bottles => $case->{input}{startBottles}, + verses => $case->{input}{takeDown}, + } + ) + ) + ], + $case->{expected}, + $case->{description} + ); +} + +sub recurse_cases { + my $obj = shift; + return $obj->{cases} + ? map recurse_cases($_), @{ $obj->{cases} } + : $obj; +} + +__DATA__ +{ + "exercise": "beer-song", + "version": "2.1.0", + "cases": [ + { + "description": "verse", + "cases": [ + { + "description": "single verse", + "cases": [ + { + "description": "first generic verse", + "property": "recite", + "input": { + "startBottles": 99, + "takeDown": 1 + }, + "expected": [ + "99 bottles of beer on the wall, 99 bottles of beer.", + "Take one down and pass it around, 98 bottles of beer on the wall." + ] + }, + { + "description": "last generic verse", + "property": "recite", + "input": { + "startBottles": 3, + "takeDown": 1 + }, + "expected": [ + "3 bottles of beer on the wall, 3 bottles of beer.", + "Take one down and pass it around, 2 bottles of beer on the wall." + ] + }, + { + "description": "verse with 2 bottles", + "property": "recite", + "input": { + "startBottles": 2, + "takeDown": 1 + }, + "expected": [ + "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." + ] + }, + { + "description": "verse with 1 bottle", + "property": "recite", + "input": { + "startBottles": 1, + "takeDown": 1 + }, + "expected": [ + "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." + ] + }, + { + "description": "verse with 0 bottles", + "property": "recite", + "input": { + "startBottles": 0, + "takeDown": 1 + }, + "expected": [ + "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." + ] + } + ] + } + ] + }, + { + "description": "lyrics", + "cases": [ + { + "description": "multiple verses", + "cases": [ + { + "description": "first two verses", + "property": "recite", + "input": { + "startBottles": 99, + "takeDown": 2 + }, + "expected": [ + "99 bottles of beer on the wall, 99 bottles of beer.", + "Take one down and pass it around, 98 bottles of beer on the wall.", + "", + "98 bottles of beer on the wall, 98 bottles of beer.", + "Take one down and pass it around, 97 bottles of beer on the wall." + ] + }, + { + "description": "last three verses", + "property": "recite", + "input": { + "startBottles": 2, + "takeDown": 3 + }, + "expected": [ + "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.", + "", + "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.", + "", + "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." + ] + }, + { + "description": "all verses", + "property": "recite", + "input": { + "startBottles": 99, + "takeDown": 100 + }, + "expected": [ + "99 bottles of beer on the wall, 99 bottles of beer.", + "Take one down and pass it around, 98 bottles of beer on the wall.", + "", + "98 bottles of beer on the wall, 98 bottles of beer.", + "Take one down and pass it around, 97 bottles of beer on the wall.", + "", + "97 bottles of beer on the wall, 97 bottles of beer.", + "Take one down and pass it around, 96 bottles of beer on the wall.", + "", + "96 bottles of beer on the wall, 96 bottles of beer.", + "Take one down and pass it around, 95 bottles of beer on the wall.", + "", + "95 bottles of beer on the wall, 95 bottles of beer.", + "Take one down and pass it around, 94 bottles of beer on the wall.", + "", + "94 bottles of beer on the wall, 94 bottles of beer.", + "Take one down and pass it around, 93 bottles of beer on the wall.", + "", + "93 bottles of beer on the wall, 93 bottles of beer.", + "Take one down and pass it around, 92 bottles of beer on the wall.", + "", + "92 bottles of beer on the wall, 92 bottles of beer.", + "Take one down and pass it around, 91 bottles of beer on the wall.", + "", + "91 bottles of beer on the wall, 91 bottles of beer.", + "Take one down and pass it around, 90 bottles of beer on the wall.", + "", + "90 bottles of beer on the wall, 90 bottles of beer.", + "Take one down and pass it around, 89 bottles of beer on the wall.", + "", + "89 bottles of beer on the wall, 89 bottles of beer.", + "Take one down and pass it around, 88 bottles of beer on the wall.", + "", + "88 bottles of beer on the wall, 88 bottles of beer.", + "Take one down and pass it around, 87 bottles of beer on the wall.", + "", + "87 bottles of beer on the wall, 87 bottles of beer.", + "Take one down and pass it around, 86 bottles of beer on the wall.", + "", + "86 bottles of beer on the wall, 86 bottles of beer.", + "Take one down and pass it around, 85 bottles of beer on the wall.", + "", + "85 bottles of beer on the wall, 85 bottles of beer.", + "Take one down and pass it around, 84 bottles of beer on the wall.", + "", + "84 bottles of beer on the wall, 84 bottles of beer.", + "Take one down and pass it around, 83 bottles of beer on the wall.", + "", + "83 bottles of beer on the wall, 83 bottles of beer.", + "Take one down and pass it around, 82 bottles of beer on the wall.", + "", + "82 bottles of beer on the wall, 82 bottles of beer.", + "Take one down and pass it around, 81 bottles of beer on the wall.", + "", + "81 bottles of beer on the wall, 81 bottles of beer.", + "Take one down and pass it around, 80 bottles of beer on the wall.", + "", + "80 bottles of beer on the wall, 80 bottles of beer.", + "Take one down and pass it around, 79 bottles of beer on the wall.", + "", + "79 bottles of beer on the wall, 79 bottles of beer.", + "Take one down and pass it around, 78 bottles of beer on the wall.", + "", + "78 bottles of beer on the wall, 78 bottles of beer.", + "Take one down and pass it around, 77 bottles of beer on the wall.", + "", + "77 bottles of beer on the wall, 77 bottles of beer.", + "Take one down and pass it around, 76 bottles of beer on the wall.", + "", + "76 bottles of beer on the wall, 76 bottles of beer.", + "Take one down and pass it around, 75 bottles of beer on the wall.", + "", + "75 bottles of beer on the wall, 75 bottles of beer.", + "Take one down and pass it around, 74 bottles of beer on the wall.", + "", + "74 bottles of beer on the wall, 74 bottles of beer.", + "Take one down and pass it around, 73 bottles of beer on the wall.", + "", + "73 bottles of beer on the wall, 73 bottles of beer.", + "Take one down and pass it around, 72 bottles of beer on the wall.", + "", + "72 bottles of beer on the wall, 72 bottles of beer.", + "Take one down and pass it around, 71 bottles of beer on the wall.", + "", + "71 bottles of beer on the wall, 71 bottles of beer.", + "Take one down and pass it around, 70 bottles of beer on the wall.", + "", + "70 bottles of beer on the wall, 70 bottles of beer.", + "Take one down and pass it around, 69 bottles of beer on the wall.", + "", + "69 bottles of beer on the wall, 69 bottles of beer.", + "Take one down and pass it around, 68 bottles of beer on the wall.", + "", + "68 bottles of beer on the wall, 68 bottles of beer.", + "Take one down and pass it around, 67 bottles of beer on the wall.", + "", + "67 bottles of beer on the wall, 67 bottles of beer.", + "Take one down and pass it around, 66 bottles of beer on the wall.", + "", + "66 bottles of beer on the wall, 66 bottles of beer.", + "Take one down and pass it around, 65 bottles of beer on the wall.", + "", + "65 bottles of beer on the wall, 65 bottles of beer.", + "Take one down and pass it around, 64 bottles of beer on the wall.", + "", + "64 bottles of beer on the wall, 64 bottles of beer.", + "Take one down and pass it around, 63 bottles of beer on the wall.", + "", + "63 bottles of beer on the wall, 63 bottles of beer.", + "Take one down and pass it around, 62 bottles of beer on the wall.", + "", + "62 bottles of beer on the wall, 62 bottles of beer.", + "Take one down and pass it around, 61 bottles of beer on the wall.", + "", + "61 bottles of beer on the wall, 61 bottles of beer.", + "Take one down and pass it around, 60 bottles of beer on the wall.", + "", + "60 bottles of beer on the wall, 60 bottles of beer.", + "Take one down and pass it around, 59 bottles of beer on the wall.", + "", + "59 bottles of beer on the wall, 59 bottles of beer.", + "Take one down and pass it around, 58 bottles of beer on the wall.", + "", + "58 bottles of beer on the wall, 58 bottles of beer.", + "Take one down and pass it around, 57 bottles of beer on the wall.", + "", + "57 bottles of beer on the wall, 57 bottles of beer.", + "Take one down and pass it around, 56 bottles of beer on the wall.", + "", + "56 bottles of beer on the wall, 56 bottles of beer.", + "Take one down and pass it around, 55 bottles of beer on the wall.", + "", + "55 bottles of beer on the wall, 55 bottles of beer.", + "Take one down and pass it around, 54 bottles of beer on the wall.", + "", + "54 bottles of beer on the wall, 54 bottles of beer.", + "Take one down and pass it around, 53 bottles of beer on the wall.", + "", + "53 bottles of beer on the wall, 53 bottles of beer.", + "Take one down and pass it around, 52 bottles of beer on the wall.", + "", + "52 bottles of beer on the wall, 52 bottles of beer.", + "Take one down and pass it around, 51 bottles of beer on the wall.", + "", + "51 bottles of beer on the wall, 51 bottles of beer.", + "Take one down and pass it around, 50 bottles of beer on the wall.", + "", + "50 bottles of beer on the wall, 50 bottles of beer.", + "Take one down and pass it around, 49 bottles of beer on the wall.", + "", + "49 bottles of beer on the wall, 49 bottles of beer.", + "Take one down and pass it around, 48 bottles of beer on the wall.", + "", + "48 bottles of beer on the wall, 48 bottles of beer.", + "Take one down and pass it around, 47 bottles of beer on the wall.", + "", + "47 bottles of beer on the wall, 47 bottles of beer.", + "Take one down and pass it around, 46 bottles of beer on the wall.", + "", + "46 bottles of beer on the wall, 46 bottles of beer.", + "Take one down and pass it around, 45 bottles of beer on the wall.", + "", + "45 bottles of beer on the wall, 45 bottles of beer.", + "Take one down and pass it around, 44 bottles of beer on the wall.", + "", + "44 bottles of beer on the wall, 44 bottles of beer.", + "Take one down and pass it around, 43 bottles of beer on the wall.", + "", + "43 bottles of beer on the wall, 43 bottles of beer.", + "Take one down and pass it around, 42 bottles of beer on the wall.", + "", + "42 bottles of beer on the wall, 42 bottles of beer.", + "Take one down and pass it around, 41 bottles of beer on the wall.", + "", + "41 bottles of beer on the wall, 41 bottles of beer.", + "Take one down and pass it around, 40 bottles of beer on the wall.", + "", + "40 bottles of beer on the wall, 40 bottles of beer.", + "Take one down and pass it around, 39 bottles of beer on the wall.", + "", + "39 bottles of beer on the wall, 39 bottles of beer.", + "Take one down and pass it around, 38 bottles of beer on the wall.", + "", + "38 bottles of beer on the wall, 38 bottles of beer.", + "Take one down and pass it around, 37 bottles of beer on the wall.", + "", + "37 bottles of beer on the wall, 37 bottles of beer.", + "Take one down and pass it around, 36 bottles of beer on the wall.", + "", + "36 bottles of beer on the wall, 36 bottles of beer.", + "Take one down and pass it around, 35 bottles of beer on the wall.", + "", + "35 bottles of beer on the wall, 35 bottles of beer.", + "Take one down and pass it around, 34 bottles of beer on the wall.", + "", + "34 bottles of beer on the wall, 34 bottles of beer.", + "Take one down and pass it around, 33 bottles of beer on the wall.", + "", + "33 bottles of beer on the wall, 33 bottles of beer.", + "Take one down and pass it around, 32 bottles of beer on the wall.", + "", + "32 bottles of beer on the wall, 32 bottles of beer.", + "Take one down and pass it around, 31 bottles of beer on the wall.", + "", + "31 bottles of beer on the wall, 31 bottles of beer.", + "Take one down and pass it around, 30 bottles of beer on the wall.", + "", + "30 bottles of beer on the wall, 30 bottles of beer.", + "Take one down and pass it around, 29 bottles of beer on the wall.", + "", + "29 bottles of beer on the wall, 29 bottles of beer.", + "Take one down and pass it around, 28 bottles of beer on the wall.", + "", + "28 bottles of beer on the wall, 28 bottles of beer.", + "Take one down and pass it around, 27 bottles of beer on the wall.", + "", + "27 bottles of beer on the wall, 27 bottles of beer.", + "Take one down and pass it around, 26 bottles of beer on the wall.", + "", + "26 bottles of beer on the wall, 26 bottles of beer.", + "Take one down and pass it around, 25 bottles of beer on the wall.", + "", + "25 bottles of beer on the wall, 25 bottles of beer.", + "Take one down and pass it around, 24 bottles of beer on the wall.", + "", + "24 bottles of beer on the wall, 24 bottles of beer.", + "Take one down and pass it around, 23 bottles of beer on the wall.", + "", + "23 bottles of beer on the wall, 23 bottles of beer.", + "Take one down and pass it around, 22 bottles of beer on the wall.", + "", + "22 bottles of beer on the wall, 22 bottles of beer.", + "Take one down and pass it around, 21 bottles of beer on the wall.", + "", + "21 bottles of beer on the wall, 21 bottles of beer.", + "Take one down and pass it around, 20 bottles of beer on the wall.", + "", + "20 bottles of beer on the wall, 20 bottles of beer.", + "Take one down and pass it around, 19 bottles of beer on the wall.", + "", + "19 bottles of beer on the wall, 19 bottles of beer.", + "Take one down and pass it around, 18 bottles of beer on the wall.", + "", + "18 bottles of beer on the wall, 18 bottles of beer.", + "Take one down and pass it around, 17 bottles of beer on the wall.", + "", + "17 bottles of beer on the wall, 17 bottles of beer.", + "Take one down and pass it around, 16 bottles of beer on the wall.", + "", + "16 bottles of beer on the wall, 16 bottles of beer.", + "Take one down and pass it around, 15 bottles of beer on the wall.", + "", + "15 bottles of beer on the wall, 15 bottles of beer.", + "Take one down and pass it around, 14 bottles of beer on the wall.", + "", + "14 bottles of beer on the wall, 14 bottles of beer.", + "Take one down and pass it around, 13 bottles of beer on the wall.", + "", + "13 bottles of beer on the wall, 13 bottles of beer.", + "Take one down and pass it around, 12 bottles of beer on the wall.", + "", + "12 bottles of beer on the wall, 12 bottles of beer.", + "Take one down and pass it around, 11 bottles of beer on the wall.", + "", + "11 bottles of beer on the wall, 11 bottles of beer.", + "Take one down and pass it around, 10 bottles of beer on the wall.", + "", + "10 bottles of beer on the wall, 10 bottles of beer.", + "Take one down and pass it around, 9 bottles of beer on the wall.", + "", + "9 bottles of beer on the wall, 9 bottles of beer.", + "Take one down and pass it around, 8 bottles of beer on the wall.", + "", + "8 bottles of beer on the wall, 8 bottles of beer.", + "Take one down and pass it around, 7 bottles of beer on the wall.", + "", + "7 bottles of beer on the wall, 7 bottles of beer.", + "Take one down and pass it around, 6 bottles of beer on the wall.", + "", + "6 bottles of beer on the wall, 6 bottles of beer.", + "Take one down and pass it around, 5 bottles of beer on the wall.", + "", + "5 bottles of beer on the wall, 5 bottles of beer.", + "Take one down and pass it around, 4 bottles of beer on the wall.", + "", + "4 bottles of beer on the wall, 4 bottles of beer.", + "Take one down and pass it around, 3 bottles of beer on the wall.", + "", + "3 bottles of beer on the wall, 3 bottles of beer.", + "Take one down and pass it around, 2 bottles of beer on the wall.", + "", + "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.", + "", + "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.", + "", + "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." + ] + } + ] + } + ] + } + ] +} diff --git a/exercises/beer-song/beer.t b/exercises/beer-song/beer.t deleted file mode 100755 index d8866a50..00000000 --- a/exercises/beer-song/beer.t +++ /dev/null @@ -1,121 +0,0 @@ -#!/usr/bin/env perl -use strict; -use warnings; - -use Test2::Bundle::More; -use FindBin qw($Bin); -use lib $Bin, "$Bin/local/lib/perl5"; - -my $module = 'Beer'; - -use JSON::PP qw(decode_json); - -my $cases; -{ - local $/ = undef; - $cases = decode_json scalar ; -} - -#diag explain $cases; -plan 4 + @$cases; - -ok -e "$Bin/$module.pm", "missing $module.pm" - or BAIL_OUT("You need to create a class called $module.pm"); - -eval "use $module"; -ok !$@, "Cannot load $module.pm" - or BAIL_OUT("Does $module.pm compile? Does it end with 1; ?"); - -can_ok( $module, 'verse' ) - or BAIL_OUT("Missing package $module; or missing sub verse()"); -can_ok( $module, 'sing' ) - or BAIL_OUT("Missing package $module; or missing sub sing()"); - -foreach my $c (@$cases) { - no strict 'refs'; - my $sub = $module . '::' . $c->{sub}; - my $expected = join '' => @{ $c->{expected} }; - - if ( $c->{sub} eq 'verse' ) { - is_deeply $sub->( $c->{input} ), $expected, $c->{name}; - } - if ( $c->{sub} eq 'sing' ) { - is_deeply $sub->( @{ $c->{input} } ), $expected, $c->{name}; - } -} - -__DATA__ -[ - { - "sub" : "verse", - "input" : 8, - "name" : "test verse 8", - "expected" : [ - "8 bottles of beer on the wall, 8 bottles of beer.\n", - "Take one down and pass it around, 7 bottles of beer on the wall.\n" - ] - }, - { - "sub" : "verse", - "input" : 1, - "name" : "test verse 1", - "expected" : [ - "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" - ] - }, - { - "sub" : "verse", - "input" : 2, - "name" : "test verse 2", - "expected" : [ - "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" - ] - }, - { - "sub" : "verse", - "input" : 0, - "name" : "test verse zero, no more bottles", - "expected" : [ - "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" - ] - }, - { - "sub" : "sing", - "input" : [8, 6], - "name" : "test sing from N bottle to N bottle", - "expected" : [ - "8 bottles of beer on the wall, 8 bottles of beer.\n", - "Take one down and pass it around, 7 bottles of beer on the wall.\n", - "\n", - "7 bottles of beer on the wall, 7 bottles of beer.\n", - "Take one down and pass it around, 6 bottles of beer on the wall.\n", - "\n", - "6 bottles of beer on the wall, 6 bottles of beer.\n", - "Take one down and pass it around, 5 bottles of beer on the wall.\n", - "\n" - ] - }, - { - "sub" : "sing", - "input" : [3], - "name" : "test sing from N bottles to no more", - "expected" : [ - "3 bottles of beer on the wall, 3 bottles of beer.\n", - "Take one down and pass it around, 2 bottles of beer on the wall.\n", - "\n", - "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", - "\n", - "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", - "\n", - "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", - "\n" - ] - } - -]