diff options
| -rw-r--r-- | challenge-336/packy-anderson/README.md | 2 | ||||
| -rw-r--r-- | challenge-336/packy-anderson/blog.txt | 1 | ||||
| -rwxr-xr-x | challenge-336/packy-anderson/elixir/ch-1.exs | 97 | ||||
| -rwxr-xr-x | challenge-336/packy-anderson/elixir/ch-2.exs | 74 | ||||
| -rwxr-xr-x | challenge-336/packy-anderson/perl/ch-1.pl | 89 | ||||
| -rwxr-xr-x | challenge-336/packy-anderson/perl/ch-2.pl | 52 | ||||
| -rwxr-xr-x | challenge-336/packy-anderson/python/ch-1.py | 75 | ||||
| -rwxr-xr-x | challenge-336/packy-anderson/python/ch-2.py | 53 | ||||
| -rwxr-xr-x | challenge-336/packy-anderson/raku/ch-1.raku | 77 | ||||
| -rwxr-xr-x | challenge-336/packy-anderson/raku/ch-2.raku | 49 |
10 files changed, 568 insertions, 1 deletions
diff --git a/challenge-336/packy-anderson/README.md b/challenge-336/packy-anderson/README.md index 83462935ff..64c1d65b5e 100644 --- a/challenge-336/packy-anderson/README.md +++ b/challenge-336/packy-anderson/README.md @@ -23,4 +23,4 @@ ## Blog Post -[Perl Weekly Challenge: Fanfare for the Common Character](https://packy.dardan.com/b/_V) +[Perl Weekly Challenge: The Score for Group Therapy](https://packy.dardan.com/b/a9) diff --git a/challenge-336/packy-anderson/blog.txt b/challenge-336/packy-anderson/blog.txt new file mode 100644 index 0000000000..ed45643d4a --- /dev/null +++ b/challenge-336/packy-anderson/blog.txt @@ -0,0 +1 @@ +https://packy.dardan.com/b/a9
\ No newline at end of file diff --git a/challenge-336/packy-anderson/elixir/ch-1.exs b/challenge-336/packy-anderson/elixir/ch-1.exs new file mode 100755 index 0000000000..00cffe4844 --- /dev/null +++ b/challenge-336/packy-anderson/elixir/ch-1.exs @@ -0,0 +1,97 @@ +#!/usr/bin/env elixir + +defmodule PWC do + def divides_unevenly(smallest, bag) do + bag + |> Map.values + |> Enum.filter(fn v -> rem(v, smallest) != 0 end) + |> length != 0 + end + + def find_smallest(smallest, _) when smallest <= 2, + do: 2 + + def find_smallest(smallest, bag) when smallest > 2 do + # can we divide the list evenly into multiples + # of the smallest group? + if divides_unevenly(smallest, bag) do + # no, let's divide it by 2 and try again + find_smallest(trunc(smallest/2), bag) + else + smallest + end + end + + def render_groups(stream) do + stream + |> Enum.to_list + |> Enum.map(fn l -> "(" <> Enum.join(l,",") <> ")" end) + |> Enum.join(" ") + end + + def equal_group(ints, bag) do + # find the smallest number of instances of + # an int in the list + smallest = Map.values(bag) |> Enum.min |> find_smallest(bag) + + # make the groups and return the result + if divides_unevenly(smallest, bag) do + # we can't evenly divide by smallest, just + # make a single group for each unique int + { + "false", + ints |> Stream.chunk_by(&(&1)) |> render_groups + } + else + # make groups of smallest + { + "true", + ints |> Stream.chunk_every(smallest) |> render_groups + } + end + end + + def equal_group(ints) do + bag = Enum.frequencies(ints) # one line bag! + if Enum.any?(Map.values(bag), fn v -> v < 2 end) do + # if we don't have more than 2 instances of + # a particular int, we can't make groups + {"false", ""} + else + equal_group(ints, bag) + end + end + + def solution(ints) do + IO.puts("Input: @ints = (" <> Enum.join(ints, ",") <> ")") + {result, groups} = equal_group(ints) + IO.puts("Output: #{result}") + if groups != "" do + IO.puts("\nGroups: #{groups}") + end + end +end + +IO.puts("Example 1:") +PWC.solution([1,1,2,2,2,2]) + +IO.puts("\nExample 2:") +PWC.solution([1,1,1,2,2,2,3,3]) + +IO.puts("\nExample 3:") +PWC.solution([5,5,5,5,5,5,7,7,7,7,7,7]) + +IO.puts("\nExample 4:") +PWC.solution([1,2,3,4]) + +IO.puts("\nExample 5:") +PWC.solution([8,8,9,9,10,10,11,11]) + +IO.puts("\nExample 6 (2a):") +PWC.solution([1,1,1,1,2,2,2,2,3,3]) + +IO.puts("\nExample 7 (2b):") +PWC.solution([1,1,1,1,1,1,1,1,1,2,2,2,2,2,2,2,2,2,3,3,3,3,3,3]) + +IO.puts("\nExample 8 (3a):") +PWC.solution([5,5,5,5,5,7,7,7,7,7,7]) diff --git a/challenge-336/packy-anderson/elixir/ch-2.exs b/challenge-336/packy-anderson/elixir/ch-2.exs new file mode 100755 index 0000000000..1dfd9b181b --- /dev/null +++ b/challenge-336/packy-anderson/elixir/ch-2.exs @@ -0,0 +1,74 @@ +#!/usr/bin/env elixir + +defmodule PWC do + defp pad(num) do + String.pad_leading(to_string(num), 2) + end + + defp wrap(num) do + if num < 0 do + "(#{num})" + else + "#{num}" + end + end + + def final_score([], stack, rounds, _) do + total = Enum.sum(stack) + { total, rounds <> "\nTotal Scores: #{total}" } + end + + def final_score([action | scores], stack, rounds, count) do + previous = List.last(stack) + stack = case action do + "+" -> + {a, b} = {Enum.at(stack, -1), Enum.at(stack, -2)} + List.insert_at(stack, -1, a + b) + "C" -> + List.delete_at(stack, -1) + "D" -> + List.insert_at(stack, -1, Enum.at(stack, -1) * 2) + _ -> + List.insert_at(stack, -1, String.to_integer(action) ) + end + rounds = rounds + <> "Round #{pad(count)}: " + <> Enum.join(Enum.map(stack, &wrap/1), " + ") + <> case action do + "+" -> " (sum of previous two scores)" + "C" -> " (invalidate the previous score #{previous})" + "D" -> " (double the previous score #{previous})" + _ -> "" + end + <> "\n" + final_score(scores, stack, rounds, count+1) + end + + def final_score(scores) do + final_score(scores, [], "", 1) + end + + def solution(scores) do + score_list = scores + |> Enum.map(fn n -> "\"#{n}\"" end) + |> Enum.join(", ") + IO.puts("Input: @ints = (#{score_list})") + {output, rounds} = final_score(scores) + IO.puts("Output: #{output}\n\n#{rounds}") + end +end + +IO.puts("Example 1:") +PWC.solution(["5","2","C","D","+"]) + +IO.puts("\nExample 2:") +PWC.solution(["5","-2","4","C","D","9","+","+"]) + +IO.puts("\nExample 3:") +PWC.solution(["7","D","D","C","+","3"]) + +IO.puts("\nExample 4:") +PWC.solution(["-5","-10","+","D","C","+"]) + +IO.puts("\nExample 5:") +PWC.solution(["3","6","+","D","C","8","+","D","-2","C","+"]) diff --git a/challenge-336/packy-anderson/perl/ch-1.pl b/challenge-336/packy-anderson/perl/ch-1.pl new file mode 100755 index 0000000000..2f044a1bf7 --- /dev/null +++ b/challenge-336/packy-anderson/perl/ch-1.pl @@ -0,0 +1,89 @@ +#!/usr/bin/env perl +use v5.40; + +use List::AllUtils qw( any min ); +use Set::Bag; + +# for some reason, Set::Bag doesn't have a method that +# will return a list of ALL the values. if $bag->grab() +# is called with a list of keys, it returns the values +# for those keys, but if it's called with no keys, it +# returns a hash of keys => values. so I rolled my own +# method to return a list of all the values... +sub bag_values($bag) { $bag->grab($bag->elements) } + +sub dividesUnevenly($smallest, $bag) { + any { $_ % $smallest != 0 } values(%$bag) +} + +sub equalGroup(@ints) { + my $bag = Set::Bag->new( map { $_ => 1 } @ints ); + # if we don't have more than 2 instances of + # a particular int, we can't make groups + return ("false", q{}) if any { $_ < 2 } values(%$bag); + + # find the smallest number of instances of + # an int in the list + my $smallest = min values(%$bag); + + # can we divide the list evenly into multiples + # of the smallest group? + while (dividesUnevenly($smallest, $bag) && $smallest > 2) { + # no, let's divide it by 2 and try again + $smallest = int($smallest / 2); + } + + # make the groups and return the result + my $groups; + if (dividesUnevenly($smallest, $bag)) { + # we can't evenly divide by $smallest, just + # make a single group for each unique int + foreach my $k ( $bag->elements ) { + my $count = $bag->grab($k); + $groups .= '(' . join(',', (($k) x $count)) . ') '; + } + return ("false", $groups); + } + else { + # make groups of $smallest + foreach my $k ( $bag->elements ) { + my $count = $bag->grab($k); + while ($count) { + $groups .= '(' . join(',', (($k) x $smallest)) . ') '; + $count -= $smallest; + } + } + return ("true", $groups); + } +} + +sub solution($ints) { + say 'Input: @ints = (' . join(',',@$ints) . ')'; + my ($result, $groups) = equalGroup(@$ints); + say "Output: $result"; + say "\nGroups: $groups" if $groups; +} + +say "Example 1:"; +solution([1,1,2,2,2,2]); + +say "\nExample 2:"; +solution([1,1,1,2,2,2,3,3]); + +say "\nExample 3:"; +solution([5,5,5,5,5,5,7,7,7,7,7,7]); + +say "\nExample 4:"; +solution([1,2,3,4]); + +say "\nExample 5:"; +solution([8,8,9,9,10,10,11,11]); + +say "\nExample 6 (2a):"; +solution([1,1,1,1,2,2,2,2,3,3]); + +say "\nExample 7 (2b):"; +solution([1,1,1,1,1,1,1,1,1,2,2,2,2,2,2,2,2,2,3,3,3,3,3,3]); + +say "\nExample 8 (3a):"; +solution([5,5,5,5,5,7,7,7,7,7,7]); diff --git a/challenge-336/packy-anderson/perl/ch-2.pl b/challenge-336/packy-anderson/perl/ch-2.pl new file mode 100755 index 0000000000..20fdba67f9 --- /dev/null +++ b/challenge-336/packy-anderson/perl/ch-2.pl @@ -0,0 +1,52 @@ +#!/usr/bin/env perl +use v5.40; + +use List::AllUtils qw( sum ); + +sub finalScore(@scores) { + my (@stack, $rounds, $count); + foreach my $action ( @scores ) { + my $previous = $stack[-1]; + foreach ($action) { + /\+/ && do { push @stack, $stack[-1] + $stack[-2]; last }; + /C/ && do { pop @stack; last; }; + /D/ && do { push @stack, $stack[-1] * 2; last; }; + push @stack, $action; + } + $rounds .= sprintf "Round %2d: ", ++$count; + $rounds .= join(" + ", map {$_ < 0 ? "($_)" : $_} @stack); + $rounds .= " (sum of previous two scores)" + if $action eq "+"; + $rounds .= " (double the previous score $previous)" + if $action eq "D"; + $rounds .= " (invalidate the previous score $previous)" + if $action eq "C"; + $rounds .= "\n"; + } + my $sum = sum(@stack); + $rounds .= "\nTotal Scores: $sum"; + return ($sum, $rounds); +} + +sub solution($scores) { + my $list = join(', ', map { qq{"$_"} } @$scores); + say "Input: \@scores = ($list)"; + my ($output, $rounds) = finalScore(@$scores); + say "Output: $output\n\n$rounds"; +} + +say "Example 1:"; +solution(["5","2","C","D","+"]); + +say "\nExample 2:"; +solution(["5","-2","4","C","D","9","+","+"]); + +say "\nExample 3:"; +solution(["7","D","D","C","+","3"]); + +say "\nExample 4:"; +solution(["-5","-10","+","D","C","+"]); + +say "\nExample 5:"; +solution(["3","6","+","D","C","8","+","D","-2","C","+"]); + diff --git a/challenge-336/packy-anderson/python/ch-1.py b/challenge-336/packy-anderson/python/ch-1.py new file mode 100755 index 0000000000..e8f3514075 --- /dev/null +++ b/challenge-336/packy-anderson/python/ch-1.py @@ -0,0 +1,75 @@ +#!/usr/bin/env python + +from collections import Counter + +def int_join(joiner, arr): + return joiner.join(map(lambda i: str(i), arr)) + +def divides_unevenly(smallest, bag): + return [ n for n in bag.values() if n % smallest != 0 ] + +def equal_group(ints): + bag = Counter(ints) + + # if we don't have more than 2 instances of + # a particular int, we can't make groups + if [ n for n in bag.values() if n < 2 ]: + return False, "" + + # find the smallest number of instances of + # an int in the list + smallest = min(bag.values()) + + # can we divide the list evenly into multiples + # of the smallest group? + while divides_unevenly(smallest, bag) and smallest > 2: + smallest = int(smallest / 2) + + # make the groups and return the result + groups = "" + if divides_unevenly(smallest, bag): + for k in bag.keys(): + group = [] + for i in range(bag[k]): group.append(k) + groups += "(" + int_join(",",group) + ") " + return False, groups + else: + for k in bag.keys(): + count = bag[k] + while count > 0: + group = [] + for i in range(smallest): group.append(k) + groups += "(" + int_join(",",group) + ") " + count -= smallest + return True, groups + +def solution(ints): + print(f'Input: @ints = ({int_join(",", ints)})') + result, groups = equal_group(ints) + print(f'Output: {result}') + if groups != "": + print(f'\nGroups: {groups}') + +print('Example 1:') +solution([1,1,2,2,2,2]) + +print('\nExample 2:') +solution([1,1,1,2,2,2,3,3]) + +print('\nExample 3:') +solution([5,5,5,5,5,5,7,7,7,7,7,7]) + +print('\nExample 4:') +solution([1,2,3,4]) + +print('\nExample 5:') +solution([8,8,9,9,10,10,11,11]) + +print('\nExample 6 (2a):') +solution([1,1,1,1,2,2,2,2,3,3]) + +print('\nExample 7 (2b):') +solution([1,1,1,1,1,1,1,1,1,2,2,2,2,2,2,2,2,2,3,3,3,3,3,3]) + +print('\nExample 8 (3a):') +solution([5,5,5,5,5,7,7,7,7,7,7])
\ No newline at end of file diff --git a/challenge-336/packy-anderson/python/ch-2.py b/challenge-336/packy-anderson/python/ch-2.py new file mode 100755 index 0000000000..4d43d4745b --- /dev/null +++ b/challenge-336/packy-anderson/python/ch-2.py @@ -0,0 +1,53 @@ +#!/usr/bin/env python + +def final_score(scores): + stack = [] + rounds = "" + count = 0 + for action in scores: + if stack: previous = stack[-1] + match action: + case '+': + stack.append( stack[-1] + stack[-2] ) + case 'C': + stack.pop() + case 'D': + stack.append( stack[-1] * 2 ) + case _: + stack.append( int(action) ) + count += 1 + rounds += "Round {:2d}: ".format(count) + rounds += " + ".join([ + f'({n})' if n < 0 else f'{n}' for n in stack + ]) + if action == "+": + rounds += " (sum of previous two scores)" + if action == "D": + rounds += f" (double the previous score {previous})" + if action == "C": + rounds += f" (invalidate the previous score {previous})" + rounds += "\n" + total = sum(stack) + rounds += f"\nTotal Scores: {total}" + return (total, rounds) + +def solution(scores): + score_list = ', '.join([ f'"{s}"' for s in scores ]) + print(f'Input: @scores = ({score_list})') + output, rounds = final_score(scores) + print(f'Output: {output}\n\n{rounds}') + +print('Example 1:') +solution(["5","2","C","D","+"]) + +print('\nExample 2:') +solution(["5","-2","4","C","D","9","+","+"]) + +print('\nExample 3:') +solution(["7","D","D","C","+","3"]) + +print('\nExample 4:') +solution(["-5","-10","+","D","C","+"]) + +print('\nExample 5:') +solution(["3","6","+","D","C","8","+","D","-2","C","+"]) diff --git a/challenge-336/packy-anderson/raku/ch-1.raku b/challenge-336/packy-anderson/raku/ch-1.raku new file mode 100755 index 0000000000..4b73cbd5dd --- /dev/null +++ b/challenge-336/packy-anderson/raku/ch-1.raku @@ -0,0 +1,77 @@ +#!/usr/bin/env raku +use v6; + +sub dividesUnevenly($smallest, $bag) { + $bag.values.grep({ $_ mod $smallest != 0 }) +} + +sub equalGroup(@ints) { + my $bag = @ints.Bag; + # if we don't have more than 2 instances of + # a particular int, we can't make groups + return (False, q{}) if $bag.values.any < 2; + + # find the smallest number of instances of + # an int in the list + my $smallest = $bag.values.min; + + # can we divide the list evenly into multiples + # of the smallest group? + while (dividesUnevenly($smallest, $bag) && $smallest > 2) { + # no, let's divide it by 2 and try again + $smallest = ($smallest / 2).Int; + } + + # make the groups and return the result + my $groups; + if (dividesUnevenly($smallest, $bag)) { + # we can't evenly divide by $smallest, just + # make a single group for each unique int + for $bag.keys.sort -> $k { + $groups ~= '(' ~ $bag.kxxv.grep($k).join(',') ~ ') '; + } + return (False, $groups); + } + else { + # make groups of $smallest + for $bag.keys.sort -> $k { + my $count = $bag{$k}; + while ($count) { + $groups ~= '(' ~ (($k) xx $smallest).join(',') ~ ') '; + $count -= $smallest; + } + } + return (True, $groups); + } +} + +sub solution(@ints) { + say 'Input: @ints = (' ~ @ints.join(',') ~ ')'; + my ($result, $groups) = equalGroup(@ints); + say "Output: $result"; + say "\nGroups: $groups" if $groups; +} + +say "Example 1:"; +solution([1,1,2,2,2,2]); + +say "\nExample 2:"; +solution([1,1,1,2,2,2,3,3]); + +say "\nExample 3:"; +solution([5,5,5,5,5,5,7,7,7,7,7,7]); + +say "\nExample 4:"; +solution([1,2,3,4]); + +say "\nExample 5:"; +solution([8,8,9,9,10,10,11,11]); + +say "\nExample 6 (2a):"; +solution([1,1,1,1,2,2,2,2,3,3]); + +say "\nExample 7 (2b):"; +solution([1,1,1,1,1,1,1,1,1,2,2,2,2,2,2,2,2,2,3,3,3,3,3,3]); + +say "\nExample 8 (3a):"; +solution([5,5,5,5,5,7,7,7,7,7,7]); diff --git a/challenge-336/packy-anderson/raku/ch-2.raku b/challenge-336/packy-anderson/raku/ch-2.raku new file mode 100755 index 0000000000..d15323f498 --- /dev/null +++ b/challenge-336/packy-anderson/raku/ch-2.raku @@ -0,0 +1,49 @@ +#!/usr/bin/env raku +use v6; + +sub finalScore(@scores) { + my (@stack, $rounds, $count); + for @scores -> $action { + my $previous = @stack[*-1]; + given $action { + when "+" { @stack.push( @stack[*-1] + @stack[*-2] ) } + when "C" { @stack.pop() } + when "D" { @stack.push( @stack[*-1] * 2 ) } + default { @stack.push($action) } + } + $rounds ~= sprintf "Round %2d: ", ++$count; + $rounds ~= @stack.map({$_ < 0 ?? "($_)" !! $_}).join(" + "); + $rounds ~= " (sum of previous two scores)" + if $action eq "+"; + $rounds ~= " (double the previous score $previous)" + if $action eq "D"; + $rounds ~= " (invalidate the previous score $previous)" + if $action eq "C"; + $rounds ~= "\n"; + } + my $sum = sum(@stack); + $rounds ~= "\nTotal Scores: $sum"; + return ($sum, $rounds); +} + +sub solution(@scores) { + my $list = @scores.map({ qq{"$_"} }).join(', '); + say "Input: \@scores = ($list)"; + my ($output, $rounds) = finalScore(@scores); + say "Output: $output\n\n$rounds"; +} + +say "Example 1:"; +solution(["5","2","C","D","+"]); + +say "\nExample 2:"; +solution(["5","-2","4","C","D","9","+","+"]); + +say "\nExample 3:"; +solution(["7","D","D","C","+","3"]); + +say "\nExample 4:"; +solution(["-5","-10","+","D","C","+"]); + +say "\nExample 5:"; +solution(["3","6","+","D","C","8","+","D","-2","C","+"]); |
